Skip to content

Commit

Permalink
Add redirect capabilities to Invest Controller (#627)
Browse files Browse the repository at this point in the history
* add redirect capabilities to invest controller

(cherry picked from commit f863efc)

* add allowed domains field to url config

* add library to handle allowed domains

* refactor to use new Domains library

* save session return_to only if it's allowed

* parse urls comming from settings

* decode return_to url

* move decode of return_to to domain library
  • Loading branch information
davidbeig authored Dec 13, 2024
1 parent e510fc3 commit 2245b92
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 9 deletions.
3 changes: 3 additions & 0 deletions Resources/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ url:
- /password-reset
- /signup

# Domains that are allowed by the application to redirect to outside of the platform.
allowed_domains:

# If you want to use a CDN or another web server to serve the cached images
# You can define this constants. All cached images links will point to this
# Url, event if don't exists yet.
Expand Down
10 changes: 10 additions & 0 deletions src/Goteo/Application/Event/FilterInvestFinishEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Contracts\EventDispatcher\Event;
use Goteo\Application\Session;
use Goteo\Library\Domain;
use Goteo\Model\Invest;

class FilterInvestFinishEvent extends Event
Expand Down Expand Up @@ -46,6 +48,13 @@ public function setHttpResponse(Response $response)

public function getHttpResponse() {
if($this->response) return $this->response;

$return_to = Session::get('return_to');
if ($return_to && Domain::isAllowedDomain($return_to)) {
Session::del('return_to');
return new RedirectResponse($return_to);
}

// Default is a redirection
if($this->invest->project) {
return new RedirectResponse('/invest/' . $this->invest->project . '/' . $this->invest->id . '/share');
Expand All @@ -57,4 +66,5 @@ public function getHttpResponse() {
return new RedirectResponse('/donate/' . $this->invest->id . '/share');
}
}

}
33 changes: 24 additions & 9 deletions src/Goteo/Controller/InvestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Goteo\Application\Session;
use Goteo\Application\View;
use Goteo\Core\Controller;
use Goteo\Library\Domain;
use Goteo\Library\Text;
use Goteo\Model\Invest;
use Goteo\Model\Project;
Expand Down Expand Up @@ -73,7 +74,7 @@ protected function getUser(): ?User
* the skip_login variable from project configuration
*/
private function validate(
$project_id, $reward_id = null, &$custom_amount = null, $invest = null, $login_required = true
$project_id, $reward_id = null, &$custom_amount = null, $invest = null, $login_required = true, ?Request $request = null
) {
$project = Project::get($project_id, Lang::current());
// Add analytics to config
Expand All @@ -96,11 +97,23 @@ private function validate(
Config::get('currency')
);

if ($request) {
$return_to = '';

if ($request->query->has('return_to')) {
$return_to = $request->query->get('return_to');

if (Domain::isAllowedDomain($return_to))
Session::store('return_to', $return_to);
}
}

$this->page = '/invest/' . $project_id;
$this->query = http_build_query([
'amount' => "$amount_original$currency",
'reward' => $reward_id,
'donate_amount' => "$donate_amount$currency"
'donate_amount' => "$donate_amount$currency",
'return_to' => $return_to
]);

// Some projects may have activated a non-registering investion
Expand Down Expand Up @@ -243,7 +256,7 @@ public function selectRewardAction($project_id, Request $request): Response
{
// TODO: add events
$amount = $request->query->get('amount');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false);
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false, $request);
if($reward instanceOf Response) return $reward;

// Aqui cambiar por escoger recompensa
Expand All @@ -260,7 +273,7 @@ public function selectRewardAction($project_id, Request $request): Response
public function loginAction($project_id, Request $request)
{
$amount = $request->query->get('amount');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false);
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false, $request);

if($reward instanceOf Response) return $reward;
if(!$request->query->has('return')) {
Expand All @@ -282,7 +295,7 @@ public function loginAction($project_id, Request $request)
public function signupAction($project_id, Request $request)
{
$amount = $request->query->get('amount');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false);
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, false, $request);

if($reward instanceOf Response) return $reward;
if(!$request->query->has('return')) {
Expand All @@ -307,7 +320,7 @@ public function selectPaymentMethodAction(Request $request, $project_id)
$amount = $request->query->get('amount');
$donate_amount = $request->query->getInt('donate_amount', Config::get('donate.tip_amount'));
$email = $request->query->has('email');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, 'auto');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, 'auto', $request);

if(!($this->skip_login && $email) && !Session::isLogged()) {
return $this->redirect('/invest/' . $project_id . '/signup?' . $this->query);
Expand Down Expand Up @@ -346,7 +359,7 @@ public function paymentFormAction($project_id, Request $request) {
$tip=$request->query->get('tip');
$donate_amount = $tip ? $request->query->get('donate_amount') : 0;
$amount = $amount_original = $request->query->get('amount');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, 'auto');
$reward = $this->validate($project_id, $request->query->get('reward'), $amount, null, 'auto', $request);

if($reward instanceOf Response) return $reward;

Expand Down Expand Up @@ -601,13 +614,15 @@ public function userDataAction($project_id, $invest_id, Request $request)
}
}
$invest->extra_info = $invest_address['extra_info'];
$invest->save();
$invest->save($errors);

if($ok && $invest->setAddress($invest_address)) {
$isAddressValid = $invest->setAddress($invest_address);
if($ok && $isAddressValid) {
return $this->dispatch(AppEvents::INVEST_FINISHED, new FilterInvestFinishEvent($invest, $request))->getHttpResponse();
}
}
Message::error(Text::get('invest-address-fail'));
Message::error(implode(',', $errors));
}

return $this->viewResponse(
Expand Down
35 changes: 35 additions & 0 deletions src/Goteo/Library/Domain.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Goteo\Library;

use Goteo\Application\Config;
use Goteo\Application\Config\ConfigException;

class Domain
{
public static function isAllowedDomain(string $domain): bool
{
try {
$domains = Config::get('url.allowed_domains');
} catch (ConfigException $e) {
return false;
}

if (empty($domains))
return false;

$parse = parse_url(rawurldecode($domain), PHP_URL_HOST);
if (!$parse)
return false;

$validDomains = array_filter($domains, function ($domain) use ($parse) {
$parsedDomain = parse_url($domain);
if (!$parsedDomain['scheme'])
return $parsedDomain['path'] == $parse;

return $parsedDomain['host'] == $parse;
});

return !empty($validDomains);
}
}

0 comments on commit 2245b92

Please sign in to comment.