cms/administrator/components/com_privacy/src/Controller/RequestController.php

421 lines
9.7 KiB
PHP

<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Privacy\Administrator\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\FormController;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Privacy\Administrator\Model\ExportModel;
use Joomla\Component\Privacy\Administrator\Model\RemoveModel;
use Joomla\Component\Privacy\Administrator\Model\RequestModel;
use Joomla\Component\Privacy\Administrator\Table\RequestTable;
/**
* Request management controller class.
*
* @since 3.9.0
*/
class RequestController extends FormController
{
/**
* Method to complete a request.
*
* @param string $key The name of the primary key of the URL variable.
* @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions).
*
* @return boolean
*
* @since 3.9.0
*/
public function complete($key = null, $urlVar = null)
{
// Check for request forgeries.
$this->checkToken();
/** @var RequestModel $model */
$model = $this->getModel();
/** @var RequestTable $table */
$table = $model->getTable();
// Determine the name of the primary key for the data.
if (empty($key))
{
$key = $table->getKeyName();
}
// To avoid data collisions the urlVar may be different from the primary key.
if (empty($urlVar))
{
$urlVar = $key;
}
$recordId = $this->input->getInt($urlVar);
$item = $model->getItem($recordId);
// Ensure this record can transition to the requested state
if (!$this->canTransition($item, '2'))
{
$this->setMessage(Text::_('COM_PRIVACY_ERROR_COMPLETE_TRANSITION_NOT_PERMITTED'), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Build the data array for the update
$data = [
$key => $recordId,
'status' => '2',
];
// Access check.
if (!$this->allowSave($data, $key))
{
$this->setMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Attempt to save the data.
if (!$model->save($data))
{
// Redirect back to the edit screen.
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Log the request completed
$model->logRequestCompleted($recordId);
$this->setMessage(Text::_('COM_PRIVACY_REQUEST_COMPLETED'));
$url = 'index.php?option=com_privacy&view=requests';
// Check if there is a return value
$return = $this->input->get('return', null, 'base64');
if (!is_null($return) && Uri::isInternal(base64_decode($return)))
{
$url = base64_decode($return);
}
// Redirect to the list screen.
$this->setRedirect(Route::_($url, false));
return true;
}
/**
* Method to email the data export for a request.
*
* @return boolean
*
* @since 3.9.0
*/
public function emailexport()
{
// Check for request forgeries.
$this->checkToken('get');
/** @var ExportModel $model */
$model = $this->getModel('Export');
$recordId = $this->input->getUint('id');
if (!$model->emailDataExport($recordId))
{
// Redirect back to the edit screen.
$this->setMessage(Text::sprintf('COM_PRIVACY_ERROR_EXPORT_EMAIL_FAILED', $model->getError()), 'error');
}
else
{
$this->setMessage(Text::_('COM_PRIVACY_EXPORT_EMAILED'));
}
$url = 'index.php?option=com_privacy&view=requests';
// Check if there is a return value
$return = $this->input->get('return', null, 'base64');
if (!is_null($return) && Uri::isInternal(base64_decode($return)))
{
$url = base64_decode($return);
}
// Redirect to the list screen.
$this->setRedirect(Route::_($url, false));
return true;
}
/**
* Method to export the data for a request.
*
* @return $this
*
* @since 3.9.0
*/
public function export()
{
$this->input->set('view', 'export');
return $this->display();
}
/**
* Method to invalidate a request.
*
* @param string $key The name of the primary key of the URL variable.
* @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions).
*
* @return boolean
*
* @since 3.9.0
*/
public function invalidate($key = null, $urlVar = null)
{
// Check for request forgeries.
$this->checkToken();
/** @var RequestModel $model */
$model = $this->getModel();
/** @var RequestTable $table */
$table = $model->getTable();
// Determine the name of the primary key for the data.
if (empty($key))
{
$key = $table->getKeyName();
}
// To avoid data collisions the urlVar may be different from the primary key.
if (empty($urlVar))
{
$urlVar = $key;
}
$recordId = $this->input->getInt($urlVar);
$item = $model->getItem($recordId);
// Ensure this record can transition to the requested state
if (!$this->canTransition($item, '-1'))
{
$this->setMessage(Text::_('COM_PRIVACY_ERROR_INVALID_TRANSITION_NOT_PERMITTED'), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Build the data array for the update
$data = [
$key => $recordId,
'status' => '-1',
];
// Access check.
if (!$this->allowSave($data, $key))
{
$this->setMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Attempt to save the data.
if (!$model->save($data))
{
// Redirect back to the edit screen.
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
// Log the request invalidated
$model->logRequestInvalidated($recordId);
$this->setMessage(Text::_('COM_PRIVACY_REQUEST_INVALIDATED'));
$url = 'index.php?option=com_privacy&view=requests';
// Check if there is a return value
$return = $this->input->get('return', null, 'base64');
if (!is_null($return) && Uri::isInternal(base64_decode($return)))
{
$url = base64_decode($return);
}
// Redirect to the list screen.
$this->setRedirect(Route::_($url, false));
return true;
}
/**
* Method to remove the user data for a privacy remove request.
*
* @return boolean
*
* @since 3.9.0
*/
public function remove()
{
// Check for request forgeries.
$this->checkToken('request');
/** @var RemoveModel $model */
$model = $this->getModel('Remove');
$recordId = $this->input->getUint('id');
if (!$model->removeDataForRequest($recordId))
{
// Redirect back to the edit screen.
$this->setMessage(Text::sprintf('COM_PRIVACY_ERROR_REMOVE_DATA_FAILED', $model->getError()), 'error');
$this->setRedirect(
Route::_(
'index.php?option=com_privacy&view=request&id=' . $recordId, false
)
);
return false;
}
$this->setMessage(Text::_('COM_PRIVACY_DATA_REMOVED'));
$url = 'index.php?option=com_privacy&view=requests';
// Check if there is a return value
$return = $this->input->get('return', null, 'base64');
if (!is_null($return) && Uri::isInternal(base64_decode($return)))
{
$url = base64_decode($return);
}
// Redirect to the list screen.
$this->setRedirect(Route::_($url, false));
return true;
}
/**
* Function that allows child controller access to model data after the data has been saved.
*
* @param BaseDatabaseModel $model The data model object.
* @param array $validData The validated data.
*
* @return void
*
* @since 3.9.0
*/
protected function postSaveHook(BaseDatabaseModel $model, $validData = [])
{
// This hook only processes new items
if (!$model->getState($model->getName() . '.new', false))
{
return;
}
if (!$model->logRequestCreated($model->getState($model->getName() . '.id')))
{
if ($error = $model->getError())
{
$this->app->enqueueMessage($error, 'warning');
}
}
if (!$model->notifyUserAdminCreatedRequest($model->getState($model->getName() . '.id')))
{
if ($error = $model->getError())
{
$this->app->enqueueMessage($error, 'warning');
}
}
else
{
$this->app->enqueueMessage(Text::_('COM_PRIVACY_MSG_CONFIRM_EMAIL_SENT_TO_USER'));
}
}
/**
* Method to determine if an item can transition to the specified status.
*
* @param object $item The item being updated.
* @param string $newStatus The new status of the item.
*
* @return boolean
*
* @since 3.9.0
*/
private function canTransition($item, $newStatus)
{
switch ($item->status)
{
case '0':
// A pending item can only move to invalid through this controller due to the requirement for a user to confirm the request
return $newStatus === '-1';
case '1':
// A confirmed item can be marked completed or invalid
return in_array($newStatus, ['-1', '2'], true);
// An item which is already in an invalid or complete state cannot transition, likewise if we don't know the state don't change anything
case '-1':
case '2':
default:
return false;
}
}
}