From 7cd246e6c85779e82b7a1cb1a75e8d4974de1d50 Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Wed, 6 Mar 2024 15:01:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0=20rev?= =?UTF-8?q?oke=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9=20=D0=B8=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Model/AccessTokenModel.php | 3 +- .../src/Model/RevokedModelInterface.php | 8 + .../src/Model/RevokedModelTrait.php | 116 ++++++++++++++ .../src/Table/AccessTokenTable.php | 20 ++- .../src/Table/RevokedTableInterface.php | 8 + .../src/Table/RevokedTableTrait.php | 141 ++++++++++++++++++ 6 files changed, 289 insertions(+), 7 deletions(-) create mode 100644 com_oauthserver/administrator/src/Model/RevokedModelInterface.php create mode 100644 com_oauthserver/administrator/src/Model/RevokedModelTrait.php create mode 100644 com_oauthserver/administrator/src/Table/RevokedTableInterface.php create mode 100644 com_oauthserver/administrator/src/Table/RevokedTableTrait.php diff --git a/com_oauthserver/administrator/src/Model/AccessTokenModel.php b/com_oauthserver/administrator/src/Model/AccessTokenModel.php index 40267d2..bbe877f 100644 --- a/com_oauthserver/administrator/src/Model/AccessTokenModel.php +++ b/com_oauthserver/administrator/src/Model/AccessTokenModel.php @@ -6,9 +6,10 @@ use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; -class AccessTokenModel extends AdminModel +class AccessTokenModel extends AdminModel implements RevokedModelInterface { use GetItemByIdentifierTrait; + use RevokedModelTrait; public function getForm($data = [], $loadData = true): Form|bool { diff --git a/com_oauthserver/administrator/src/Model/RevokedModelInterface.php b/com_oauthserver/administrator/src/Model/RevokedModelInterface.php new file mode 100644 index 0000000..5e77469 --- /dev/null +++ b/com_oauthserver/administrator/src/Model/RevokedModelInterface.php @@ -0,0 +1,8 @@ +getCurrentUser(); + /** @var \Joomla\CMS\Table\Table $table */ + $table = $this->getTable(); + $identifiers = (array)$identifiers; + $pks = []; + + $context = $this->option . '.' . $this->name; + + // Include the plugins for the change of state event. + PluginHelper::importPlugin($this->events_map['change_state']); + + foreach ($identifiers as $i => $identifier) { + $table->reset(); + + if ($table->load(['identifier' => $identifier])) { + $revokedColumnName = $table->getColumnAlias('revoked'); + + if (property_exists($table, $revokedColumnName) && $table->get($revokedColumnName, 1) == 0) { + unset($identifier[$i]); + } else { + $pks[] = $table->get('id'); + } + } + } + + // Check if there are items to change + if (!\count($pks)) { + return true; + } + + // Trigger the before change state event. + $result = Factory::getApplication()->triggerEvent($this->event_before_change_state, [$context, $pks, 0]); + + if (\in_array(false, $result, true)) { + $this->setError($table->getError()); + + return false; + } + + // Attempt to change the state of the records. + if (!$table->revoke($pks, $user->id)) { + $this->setError($table->getError()); + + return false; + } + + // Trigger the change state event. + $result = Factory::getApplication()->triggerEvent($this->event_change_state, [$context, $pks, 0]); + + if (\in_array(false, $result, true)) { + $this->setError($table->getError()); + + return false; + } + + // Clear the component's cache + $this->cleanCache(); + + return true; + } +} \ No newline at end of file diff --git a/com_oauthserver/administrator/src/Table/AccessTokenTable.php b/com_oauthserver/administrator/src/Table/AccessTokenTable.php index 70ff734..2c019cb 100644 --- a/com_oauthserver/administrator/src/Table/AccessTokenTable.php +++ b/com_oauthserver/administrator/src/Table/AccessTokenTable.php @@ -2,16 +2,24 @@ namespace Webmasterskaya\Component\OauthServer\Administrator\Table; -use DateTimeImmutable; use Joomla\CMS\Table\Table; use Joomla\Database\DatabaseDriver; -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; -class AccessTokenTable extends Table +/** + * @property int $id + * @property string $identifier + * @property \DateTimeImmutable|\DateTime|string $expiry + * @property ?int $user_id + * @property string|array|null $scopes + * @property int $client_id + * @property int $revoked + * + * @since version + */ +class AccessTokenTable extends Table implements RevokedTableInterface { + use RevokedTableTrait; + /** * Indicates that columns fully support the NULL value in the database * diff --git a/com_oauthserver/administrator/src/Table/RevokedTableInterface.php b/com_oauthserver/administrator/src/Table/RevokedTableInterface.php new file mode 100644 index 0000000..44b9519 --- /dev/null +++ b/com_oauthserver/administrator/src/Table/RevokedTableInterface.php @@ -0,0 +1,8 @@ + $this, + 'pks' => $pks, + ] + ); + $this->getDispatcher()->dispatch('onTableBeforeRevoke', $event); + + if (!\is_null($pks)) { + if (!\is_array($pks)) { + $pks = [$pks]; + } + + foreach ($pks as $key => $pk) { + if (!\is_array($pk)) { + $pks[$key] = [$this->_tbl_key => $pk]; + } + } + } + + // If there are no primary keys set check to see if the instance key is set. + if (empty($pks)) { + $pk = []; + + foreach ($this->_tbl_keys as $key) { + if ($this->$key) { + $pk[$key] = $this->$key; + } else { + // We don't have a full primary key - return false + $this->setError(Text::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED')); + + return false; + } + } + + $pks = [$pk]; + } + + $revokedField = $this->getColumnAlias('revoked'); + + foreach ($pks as $pk) { + $query = $this->_db->getQuery(true) + ->update($this->_db->quoteName($this->_tbl)) + ->set($this->_db->quoteName($revokedField) . ' = 0'); + + // Build the WHERE clause for the primary keys. + $this->appendPrimaryKeys($query, $pk); + + $this->_db->setQuery($query); + + try { + $this->_db->execute(); + } catch (\RuntimeException $e) { + $this->setError($e->getMessage()); + + return false; + } + + // If the Table instance value is in the list of primary keys that were set, set the instance. + $ours = true; + + foreach ($this->_tbl_keys as $key) { + if ($this->$key != $pk[$key]) { + $ours = false; + } + } + + if ($ours) { + $this->$revokedField = 0; + } + } + + $this->setError(''); + + // Pre-processing by observers + $event = AbstractEvent::create( + 'onTableAfterRevoke', + [ + 'subject' => $this, + 'pks' => $pks + ] + ); + $this->getDispatcher()->dispatch('onTableAfterRevoke', $event); + + return true; + } +} \ No newline at end of file