_JEXEC & copyright

This commit is contained in:
Artem Vasilev 2024-03-09 18:55:30 +03:00
parent 16f1f08808
commit f821c9becb
6 changed files with 147 additions and 68 deletions

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
@ -6,6 +13,9 @@ use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\ParameterType; use Joomla\Database\ParameterType;
use Joomla\Database\QueryInterface;
\defined('_JEXEC') or die;
class ClientsModel extends ListModel class ClientsModel extends ListModel
{ {
@ -21,8 +31,8 @@ class ClientsModel extends ListModel
/** /**
* Constructor. * Constructor.
* *
* @param array $config An optional associative array of configuration settings. * @param array $config An optional associative array of configuration settings.
* @param MVCFactoryInterface|null $factory The factory. * @param MVCFactoryInterface|null $factory The factory.
* *
* @throws \Exception * @throws \Exception
* *
@ -31,7 +41,8 @@ class ClientsModel extends ListModel
public function __construct($config = [], MVCFactoryInterface $factory = null) public function __construct($config = [], MVCFactoryInterface $factory = null)
{ {
// Add the ordering filtering fields whitelist // Add the ordering filtering fields whitelist
if (empty($config['filter_fields'])) { if (empty($config['filter_fields']))
{
$config['filter_fields'] = [ $config['filter_fields'] = [
'id', 'client.id' 'id', 'client.id'
]; ];
@ -43,8 +54,8 @@ class ClientsModel extends ListModel
/** /**
* Method to auto-populate the model state. * Method to auto-populate the model state.
* *
* @param string $ordering An optional ordering field. * @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc). * @param string $direction An optional direction (asc|desc).
* *
* @throws \Exception * @throws \Exception
* *
@ -55,7 +66,8 @@ class ClientsModel extends ListModel
$app = Factory::getApplication(); $app = Factory::getApplication();
// Adjust the context to support modal layouts. // Adjust the context to support modal layouts.
if ($layout = $app->input->get('layout')) { if ($layout = $app->input->get('layout'))
{
$this->context .= '.' . $layout; $this->context .= '.' . $layout;
} }
@ -68,7 +80,7 @@ class ClientsModel extends ListModel
/** /**
* Method to get a store id based on model configuration state. * Method to get a store id based on model configuration state.
* *
* @param string $id A prefix for the store id. * @param string $id A prefix for the store id.
* *
* @return string A store id. * @return string A store id.
* *
@ -84,13 +96,13 @@ class ClientsModel extends ListModel
/** /**
* Method to get a DatabaseQuery object for retrieving the data set from a database. * Method to get a DatabaseQuery object for retrieving the data set from a database.
* *
* @return \Joomla\Database\QueryInterface A QueryInterface object to retrieve the data set. * @return QueryInterface A QueryInterface object to retrieve the data set.
* *
* @throws \Exception * @throws \Exception
* *
* @since 1.0.0 * @since 1.0.0
*/ */
protected function getListQuery(): \Joomla\Database\QueryInterface protected function getListQuery(): QueryInterface
{ {
$db = $this->getDatabase(); $db = $this->getDatabase();
@ -101,16 +113,17 @@ class ClientsModel extends ListModel
// Filter by search state // Filter by search state
$search = $this->getState('filter.search'); $search = $this->getState('filter.search');
if (!empty($search)) { if (!empty($search))
{
$query->where('client.name LIKE :search') $query->where('client.name LIKE :search')
->bind(':search', $search, ParameterType::STRING); ->bind(':search', $search, ParameterType::STRING);
} }
// Add the list ordering clause // Add the list ordering clause
$ordering = $this->state->get('list.ordering', 'client.id'); $ordering = $this->state->get('list.ordering', 'client.id');
$direction = $this->state->get('list.direction', 'desc'); $direction = $this->state->get('list.direction', 'desc');
$query->order($db->escape($ordering) . ' ' . $db->escape($direction)); $query->order($db->escape($ordering) . ' ' . $db->escape($direction));
return $query; return $query;
} }
} }

View File

@ -1,30 +1,37 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Table\Table;
use Joomla\Utilities\ArrayHelper; use Joomla\Utilities\ArrayHelper;
\defined('_JEXEC') or die;
trait GetItemByIdentifierTrait trait GetItemByIdentifierTrait
{ {
abstract public function getState($property = null, $default = null);
abstract public function getName();
abstract public function getTable($name = '', $prefix = '', $options = []);
public function getItemByIdentifier($identifier = null): object public function getItemByIdentifier($identifier = null): object
{ {
$identifier = (!empty($identifier)) ? $identifier : (int)$this->getState($this->getName() . '.identifier'); $identifier = (!empty($identifier)) ? $identifier : (int) $this->getState($this->getName() . '.identifier');
/** @var \Joomla\CMS\Table\Table $table */ /** @var Table $table */
$table = $this->getTable(); $table = $this->getTable();
if (!empty($identifier)) { if (!empty($identifier))
{
$return = $table->load(['identifier' => $identifier]); $return = $table->load(['identifier' => $identifier]);
if ($return === false) { if ($return === false)
if (method_exists($table, 'getError') && $table->getError()) { {
if (method_exists($table, 'getError') && $table->getError())
{
throw new \RuntimeException($table->getError()); throw new \RuntimeException($table->getError());
} }
throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_NOT_EXIST')); throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_NOT_EXIST'));
@ -32,12 +39,15 @@ trait GetItemByIdentifierTrait
} }
// Convert to the CMSObject before adding other data. // Convert to the CMSObject before adding other data.
$properties = $table->getProperties(true); $properties = $table->getProperties(true);
$all_properties = $table->getProperties(false); $all_properties = $table->getProperties(false);
if (!empty($all_properties['_jsonEncode'])) { if (!empty($all_properties['_jsonEncode']))
foreach ($all_properties['_jsonEncode'] as $prop) { {
if (array_key_exists($prop, $properties) && is_string($properties[$prop])) { foreach ($all_properties['_jsonEncode'] as $prop)
{
if (array_key_exists($prop, $properties) && is_string($properties[$prop]))
{
$properties[$prop] = json_decode($properties[$prop]); $properties[$prop] = json_decode($properties[$prop]);
} }
} }
@ -45,4 +55,10 @@ trait GetItemByIdentifierTrait
return ArrayHelper::toObject($properties, CMSObject::class, true); return ArrayHelper::toObject($properties, CMSObject::class, true);
} }
}
abstract public function getState($property = null, $default = null);
abstract public function getName();
abstract public function getTable($name = '', $prefix = '', $options = []);
}

View File

@ -1,10 +1,20 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
use Joomla\CMS\Factory; use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form; use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\MVC\Model\AdminModel;
use Webmasterskaya\Component\OauthServer\Administrator\Table\RefreshTokenTable;
\defined('_JEXEC') or die;
class RefreshTokenModel extends AdminModel implements RevokedModelInterface class RefreshTokenModel extends AdminModel implements RevokedModelInterface
{ {
@ -15,19 +25,26 @@ class RefreshTokenModel extends AdminModel implements RevokedModelInterface
{ {
$form = $this->loadForm('com_oauthserver.refresh_token', 'refresh_token', ['control' => 'jform', 'load_data' => $loadData]); $form = $this->loadForm('com_oauthserver.refresh_token', 'refresh_token', ['control' => 'jform', 'load_data' => $loadData]);
if (empty($form)) { if (empty($form))
{
return false; return false;
} }
return $form; return $form;
} }
public function getTable($name = 'RefreshToken', $prefix = 'Administrator', $options = [])
{
return parent::getTable($name, $prefix, $options);
}
protected function loadFormData(): mixed protected function loadFormData(): mixed
{ {
// Check the session for previously entered form data. // Check the session for previously entered form data.
$data = Factory::getApplication()->getUserState('com_oauthserver.edit.refresh_token.data', []); $data = Factory::getApplication()->getUserState('com_oauthserver.edit.refresh_token.data', []);
if (empty($data)) { if (empty($data))
{
$data = $this->getItem(); $data = $this->getItem();
} }
@ -37,19 +54,16 @@ class RefreshTokenModel extends AdminModel implements RevokedModelInterface
} }
/** /**
* @param \Webmasterskaya\Component\OauthServer\Administrator\Table\RefreshTokenTable $table * @param RefreshTokenTable $table
*
* @return void * @return void
* @since version * @since version
*/ */
protected function prepareTable($table) protected function prepareTable($table)
{ {
if ($table->expiry instanceof \DateTime || $table->expiry instanceof \DateTimeImmutable) { if ($table->expiry instanceof \DateTime || $table->expiry instanceof \DateTimeImmutable)
{
$table->expiry = $table->expiry->format($table->getDbo()->getDateFormat()); $table->expiry = $table->expiry->format($table->getDbo()->getDateFormat());
} }
} }
}
public function getTable($name = 'RefreshToken', $prefix = 'Administrator', $options = [])
{
return parent::getTable($name, $prefix, $options);
}
}

View File

@ -1,8 +1,17 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
\defined('_JEXEC') or die;
interface RevokedModelInterface interface RevokedModelInterface
{ {
public function revoke(&$identifiers): bool; public function revoke(&$identifiers): bool;
} }

View File

@ -1,99 +1,109 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
use Joomla\CMS\Factory; use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\User\User; use Joomla\CMS\User\User;
\defined('_JEXEC') or die;
trait RevokedModelTrait trait RevokedModelTrait
{ {
/** /**
* @var string * @var string
* @since version * @since version
* @noinspection PhpMissingFieldTypeInspection * @noinspection PhpMissingFieldTypeInspection
*/ */
protected $option; protected $option;
/** /**
* @var string * @var string
* @since version * @since version
* @noinspection PhpMissingFieldTypeInspection * @noinspection PhpMissingFieldTypeInspection
*/ */
protected $name; protected $name;
/** /**
* @var array * @var array
* @since version * @since version
* @noinspection PhpMissingFieldTypeInspection * @noinspection PhpMissingFieldTypeInspection
*/ */
protected $events_map; protected $events_map;
/** /**
* @var string * @var string
* @since version * @since version
* @noinspection PhpMissingFieldTypeInspection * @noinspection PhpMissingFieldTypeInspection
*/ */
protected $event_before_change_state; protected $event_before_change_state;
/** /**
* @var string * @var string
* @since version * @since version
* @noinspection PhpMissingFieldTypeInspection * @noinspection PhpMissingFieldTypeInspection
*/ */
protected $event_change_state; protected $event_change_state;
abstract public function getTable($name = '', $prefix = '', $options = []);
abstract protected function getCurrentUser(): User;
abstract public function setError($error);
abstract protected function cleanCache($group = null);
public function revoke(&$identifiers): bool public function revoke(&$identifiers): bool
{ {
$user = $this->getCurrentUser(); $user = $this->getCurrentUser();
/** @var \Joomla\CMS\Table\Table $table */ /** @var Table $table */
$table = $this->getTable(); $table = $this->getTable();
$identifiers = (array)$identifiers; $identifiers = (array) $identifiers;
$pks = []; $pks = [];
$context = $this->option . '.' . $this->name; $context = $this->option . '.' . $this->name;
// Include the plugins for the change of state event. // Include the plugins for the change of state event.
PluginHelper::importPlugin($this->events_map['change_state']); PluginHelper::importPlugin($this->events_map['change_state']);
foreach ($identifiers as $i => $identifier) { foreach ($identifiers as $i => $identifier)
{
$table->reset(); $table->reset();
if ($table->load(['identifier' => $identifier])) { if ($table->load(['identifier' => $identifier]))
{
$revokedColumnName = $table->getColumnAlias('revoked'); $revokedColumnName = $table->getColumnAlias('revoked');
if (property_exists($table, $revokedColumnName) && $table->get($revokedColumnName, 1) == 0) { if (property_exists($table, $revokedColumnName) && $table->get($revokedColumnName, 1) == 0)
{
unset($identifiers[$i]); unset($identifiers[$i]);
} else { }
else
{
$pks[] = $table->get('id'); $pks[] = $table->get('id');
} }
} }
} }
// Check if there are items to change // Check if there are items to change
if (!\count($pks)) { if (!\count($pks))
{
return true; return true;
} }
// Trigger the before change state event. // Trigger the before change state event.
$result = Factory::getApplication()->triggerEvent($this->event_before_change_state, [$context, $pks, 0]); $result = Factory::getApplication()->triggerEvent($this->event_before_change_state, [$context, $pks, 0]);
if (\in_array(false, $result, true)) { if (\in_array(false, $result, true))
{
$this->setError($table->getError()); $this->setError($table->getError());
return false; return false;
} }
// Attempt to change the state of the records. // Attempt to change the state of the records.
if (!$table->revoke($pks, $user->id)) { if (!$table->revoke($pks, $user->id))
{
$this->setError($table->getError()); $this->setError($table->getError());
return false; return false;
@ -102,7 +112,8 @@ trait RevokedModelTrait
// Trigger the change state event. // Trigger the change state event.
$result = Factory::getApplication()->triggerEvent($this->event_change_state, [$context, $pks, 0]); $result = Factory::getApplication()->triggerEvent($this->event_change_state, [$context, $pks, 0]);
if (\in_array(false, $result, true)) { if (\in_array(false, $result, true))
{
$this->setError($table->getError()); $this->setError($table->getError());
return false; return false;
@ -113,4 +124,12 @@ trait RevokedModelTrait
return true; return true;
} }
}
abstract protected function getCurrentUser(): User;
abstract public function getTable($name = '', $prefix = '', $options = []);
abstract public function setError($error);
abstract protected function cleanCache($group = null);
}

View File

@ -1,4 +1,11 @@
<?php <?php
/**
* @package Joomla.Administrator
* @subpackage com_oauthserver
*
* @copyright (c) 2024. Webmasterskaya. <https://webmasterskaya.xyz>
* @license MIT; see LICENSE.txt
**/
namespace Webmasterskaya\Component\OauthServer\Administrator\Model; namespace Webmasterskaya\Component\OauthServer\Administrator\Model;
@ -6,11 +13,12 @@ use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\MVC\Model\BaseModel; use Joomla\CMS\MVC\Model\BaseModel;
use Joomla\CMS\MVC\Model\ItemModelInterface; use Joomla\CMS\MVC\Model\ItemModelInterface;
\defined('_JEXEC') or die;
class ScopeModel extends BaseModel implements ItemModelInterface class ScopeModel extends BaseModel implements ItemModelInterface
{ {
private static array $_storage;
private const PREDEFINED_SCOPES = ['userinfo', 'email']; private const PREDEFINED_SCOPES = ['userinfo', 'email'];
private static array $_storage;
public function getItem($pk = null) public function getItem($pk = null)
{ {
@ -23,4 +31,4 @@ class ScopeModel extends BaseModel implements ItemModelInterface
} }
} }