Commit e2ae94f5 authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Centralize configuration for TER API

A new Configuration class is added, which contains all information
that was previously set in various places.

This change
* removes a dummy \stdObject containing random information
* removes dependencies revolving around implicit dependencies in TSFE setup variables
* Centralizes all options regarding repository path

In addition, the tx_ter_api object does need any external dependencies
loaded from e.g. pi-based plugins anymore. This way, the next step is
to build a middleware for /ter and removing the plugin alltogether.
parent 009960b1
Pipeline #9087 failed with stages
in 59 seconds
<?php
declare(strict_types=1);
namespace T3o\Ter\Api;
/*
* This file is part of TYPO3 CMS-extension "ter", created by Benni Mack.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*/
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\SingletonInterface;
/**
* Contains all static information about the TER API which is system-wide OK.
* If this should be customizable in the future, it is recommended to use env variables
*/
class Configuration implements SingletonInterface
{
/**
* @var string
*/
protected $repositoryDirectory;
/**
* @var int
*/
protected $administratorsGroupId = 26;
/**
* @var int
*/
protected $securityTeamGroupId = 22;
/**
* @var int
*/
protected $reviewersGroupId = 22;
/**
* Page ID where all tx_ter_* database records are put
* @var int
*/
protected $storagePid = 2;
public function __construct()
{
// Check extension repository path
$extensionConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ter'] ?? [];
if (empty($extensionConfig['repositoryDir'])) {
throw new \Exception('No repository path found in extension configuration', 1303220917);
}
$this->repositoryDirectory = rtrim($extensionConfig['repositoryDir'], '/') . '/';
}
public function getRepositoryBasePath(): string
{
return $this->repositoryDirectory;
}
public function getAdministratorsGroupId(): int
{
return $this->administratorsGroupId;
}
public function getSecurityUserGroupId(): int
{
return $this->securityTeamGroupId;
}
public function getReviewersUserGroupId(): int
{
return $this->reviewersGroupId;
}
public function getStoragePid(): int
{
return $this->storagePid;
}
public function getWsdlNamespace(): string
{
switch ((string)Environment::getContext()) {
case 'Production/Stage':
return 'https://extensions-stage.typo3.org/wsdl/tx_ter/';
case 'Production':
return 'https://extensions.typo3.org/wsdl/tx_ter/';
default:
return 'https://ter.ddev.site/wsdl/tx_ter/';
}
}
}
\ No newline at end of file
......@@ -22,8 +22,6 @@ Configuration
plugin.tx_ter_pi1 {
pid = 1320
repositoryDir = /var/www/sites/typo3.org/fileadmin/ter/
reviewersFrontendUsergroupUid = 123
}
page = PAGE
......
......@@ -17,10 +17,8 @@
*
* @author Robert Lemke <robert@typo3.org>
*/
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
require_once(ExtensionManagementUtility::extPath('ter') . 'class.tx_ter_helper.php');
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* TYPO3 Extension Repository, SOAP Server
......@@ -32,14 +30,14 @@ class tx_ter_api
use \Psr\Log\LoggerAwareTrait;
/**
* @var tx_ter_helper
* @var \tx_ter_helper
*/
protected $helperObj;
/**
* @var object
* @var \T3o\Ter\Api\Configuration
*/
protected $parentObj;
protected $apiConfiguration;
/**
* @var \TYPO3\CMS\Core\DataHandling\DataHandler
......@@ -53,17 +51,10 @@ class tx_ter_api
*/
protected $extensionMaxUploadSize = 31457280;
/**
* Constructor
*
* @param object $parentObj : Reference to parent object
*
* @access public
*/
public function __construct($parentObj)
public function __construct()
{
$this->helperObj = new tx_ter_helper($parentObj);
$this->parentObj = $parentObj;
$this->helperObj = new \tx_ter_helper();
$this->apiConfiguration = GeneralUtility::makeInstance(\T3o\Ter\Api\Configuration::class);
$this->setLogger(GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class)->getLogger('TER\API\SOAP'));
}
......@@ -208,13 +199,7 @@ class tx_ter_api
public static function uploadExtensionWithoutSoap($username, $extensionInfoData, $filesData)
{
// Make an instance of the api
$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['ter']);
$dummyParentObject = (object)[
'extensionsPID' => $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_ter_pi1.']['pid'],
'repositoryDir' => $extConf['repositoryDir'],
'conf' => $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_ter_pi1.'],
];
$instance = GeneralUtility::makeInstance(\tx_ter_api::class, $dummyParentObject);
$instance = GeneralUtility::makeInstance(\tx_ter_api::class);
$accountData = (object)['username' => $username];
// Load extension
$extensionKeyRecordArr = $instance->helperObj->getExtensionKeyRecord(strtolower($extensionInfoData->extensionKey));
......@@ -538,14 +523,7 @@ class tx_ter_api
public function setReviewState($accountData, $setReviewStateData)
{
$userRecordArr = $this->helperObj->getValidUser($accountData);
$reviewersFrontendUsergroupUid = (int)$GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_ter_pi1.']['reviewersFrontendUsergroupUid'];
if ($reviewersFrontendUsergroupUid == 0) {
throw new \T3o\Ter\Exception\InternalServerErrorException(
'Warning: No usergroup for reviewers has been defined on the server side. Aborting ...',
TX_TER_ERROR_SETREVIEWSTATE_NOUSERGROUPDEFINED
);
}
$reviewersFrontendUsergroupUid = $this->apiConfiguration->getReviewersUserGroupId();
if (!GeneralUtility::inList($userRecordArr['usergroup'], $reviewersFrontendUsergroupUid)) {
throw new \T3o\Ter\Exception\UnauthorizedException('Access denied.', TX_TER_ERROR_SETREVIEWSTATE_ACCESSDENIED);
}
......@@ -607,7 +585,7 @@ class tx_ter_api
*/
public function uploadExtension_writeExtensionAndIconFile(&$extensionInfoData, $filesData)
{
if (!@is_dir($this->parentObj->repositoryDir)) {
if (!@is_dir($this->apiConfiguration->getRepositoryBasePath())) {
throw new \T3o\Ter\Exception\InternalServerErrorException(
'Extension repository directory does not exist.',
TX_TER_ERROR_GENERAL_EXTREPDIRDOESNTEXIST
......@@ -706,13 +684,13 @@ class tx_ter_api
// Create directories and build filenames:
$firstLetter = strtolower(substr($extensionInfoData->extensionKey, 0, 1));
$secondLetter = strtolower(substr($extensionInfoData->extensionKey, 1, 1));
$fullPath = $this->parentObj->repositoryDir . $firstLetter . '/' . $secondLetter . '/';
$fullPath = $this->apiConfiguration->getRepositoryBasePath() . $firstLetter . '/' . $secondLetter . '/';
if (@!is_dir($this->parentObj->repositoryDir . $firstLetter)) {
mkdir($this->parentObj->repositoryDir . $firstLetter);
if (@!is_dir($this->apiConfiguration->getRepositoryBasePath() . $firstLetter)) {
mkdir($this->apiConfiguration->getRepositoryBasePath() . $firstLetter);
}
if (@!is_dir($this->parentObj->repositoryDir . $firstLetter . '/' . $secondLetter)) {
mkdir($this->parentObj->repositoryDir . $firstLetter . '/' . $secondLetter);
if (@!is_dir($this->apiConfiguration->getRepositoryBasePath() . $firstLetter . '/' . $secondLetter)) {
mkdir($this->apiConfiguration->getRepositoryBasePath() . $firstLetter . '/' . $secondLetter);
}
list($majorVersion, $minorVersion, $devVersion) = GeneralUtility::intExplode(
......@@ -802,7 +780,7 @@ class tx_ter_api
$extensionRow = [
'tstamp' => $GLOBALS['SIM_EXEC_TIME'],
'crdate' => $GLOBALS['SIM_EXEC_TIME'],
'pid' => 2,
'pid' => $this->apiConfiguration->getStoragePid(),
'extensionkey' => $extensionKey,
'version' => $extensionInfoData->version,
'title' => $extensionInfoData->metaData->title,
......@@ -847,7 +825,7 @@ class tx_ter_api
// Prepare details row
$extensionDetailsRow = [
'pid' => 2,
'pid' => $this->apiConfiguration->getStoragePid(),
'extensionuid' => (int)$extensionUid,
'uploadcomment' => (string)$extensionInfoData->infoData->uploadComment,
'lastuploadbyusername' => $accountData->username,
......@@ -883,7 +861,7 @@ class tx_ter_api
// Put new extension version into queue
$extensionQueue = [
'pid' => 2,
'pid' => $this->apiConfiguration->getStoragePid(),
'extensionuid' => (int)$extensionUid,
'extensionkey' => $extensionKey,
];
......@@ -910,7 +888,7 @@ class tx_ter_api
*/
protected function deleteExtension_deleteFromDBAndRemoveFiles($extensionKey, $version)
{
if (!@is_dir($this->parentObj->repositoryDir)) {
if (!@is_dir($this->apiConfiguration->getRepositoryBasePath())) {
throw new \T3o\Ter\Exception\InternalServerErrorException(
'Extension repository directory does not exist.',
TX_TER_ERROR_GENERAL_EXTREPDIRDOESNTEXIST
......@@ -968,7 +946,7 @@ class tx_ter_api
$firstLetter = strtolower(substr($extensionKey, 0, 1));
$secondLetter = strtolower(substr($extensionKey, 1, 1));
$fullPath = $this->parentObj->repositoryDir . $firstLetter . '/' . $secondLetter . '/';
$fullPath = $this->apiConfiguration->getRepositoryBasePath() . $firstLetter . '/' . $secondLetter . '/';
list($majorVersion, $minorVersion, $devVersion) = GeneralUtility::intExplode('.', $version);
$fullPath .= strtolower($extensionKey) . '_' . $majorVersion . '.' . $minorVersion . '.' . $devVersion;
......@@ -1185,7 +1163,7 @@ class tx_ter_api
protected function registerExtensionKey_writeExtensionKeyInfoToDB($accountData, $extensionKeyData)
{
$extensionKeysRow = [
'pid' => 2,
'pid' => $this->apiConfiguration->getStoragePid(),
'tstamp' => time(),
'crdate' => time(),
'extensionkey' => $extensionKeyData->extensionKey,
......
......@@ -81,21 +81,6 @@ define('TX_TER_RESULT_EXTENSIONSUCCESSFULLYDELETED', '10505');
*/
class tx_ter_helper
{
protected $pluginObj;
/**
* Constructor
*
* @param object $pluginObj : Reference to parent object
* @access public
*/
public function __construct($pluginObj)
{
$this->pluginObj = $pluginObj;
$this->pluginObj->conf['adminFrontendUsergroupUid'] = 26;
$this->pluginObj->conf['securityTeamFrontendUsergroupUid'] = 22;
}
/**
* This verifies the given fe_users username/password.
* Either the fe_user row is returned or an exception is thrown.
......@@ -147,7 +132,8 @@ class tx_ter_helper
*/
private function userIsAdmin(string $userGroupList): bool
{
return $this->pluginObj->conf['adminFrontendUsergroupUid'] > 0 && GeneralUtility::inList($userGroupList, (int)$this->pluginObj->conf['adminFrontendUsergroupUid']);
$groupId = GeneralUtility::makeInstance(\T3o\Ter\Api\Configuration::class)->getAdministratorsGroupId();
return GeneralUtility::inList($userGroupList, $groupId);
}
/**
......@@ -156,7 +142,8 @@ class tx_ter_helper
*/
private function userIsSecurityTeamMember(string $userGroupList): bool
{
return $this->pluginObj->conf['securityTeamFrontendUsergroupUid'] > 0 && GeneralUtility::inList($userGroupList, (int)$this->pluginObj->conf['securityTeamFrontendUsergroupUid']);
$groupId = GeneralUtility::makeInstance(\T3o\Ter\Api\Configuration::class)->getSecurityUserGroupId();
return GeneralUtility::inList($userGroupList, $groupId);
}
/**
......
......@@ -12,3 +12,14 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\T3o\Ter\Task\Up
'description' => 'LLL:EXT:ter/locallang.xml:tx_ter_updateCurrentVersionListTask.description',
'additionalFields' => ''
];
$apiConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\T3o\Ter\Api\Configuration::class);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptConstants('
plugin.tx_ter_pi1 {
pid = ' . $apiConfiguration->getStoragePid() . '
reviewersFrontendUsergroupUid = ' . $apiConfiguration->getReviewersUserGroupId() . '
adminFrontendUsergroupUid = ' . $apiConfiguration->getAdministratorsGroupId() . '
securityTeamFrontendUsergroupUid = ' . $apiConfiguration->getSecurityUserGroupId() . '
wsdlNamespace = ' . $apiConfiguration->getWsdlNamespace() . '
}
');
\ No newline at end of file
......@@ -39,25 +39,8 @@ use TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
*/
class tx_ter_pi1 extends AbstractPlugin
{
public $extensionsPID; // Start page for extension records
public $wsdlNamespace; // Namespace
public $repositoryDir; // Absolute path to extension repository directory
public $conf; // The FE Plugin's TS configuration
public function main($content, $conf)
{
$this->conf = $conf;
$this->extensionsPID = $conf['pid'];
$this->wsdlNamespace = $conf['wsdlNamespace'];
$staticConfArr = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ter'];
if (is_array($staticConfArr)) {
$this->repositoryDir = $staticConfArr['repositoryDir'];
if (substr($this->repositoryDir, -1, 1) != '/') {
$this->repositoryDir .= '/';
}
}
// Always deliver the proper WSDL file if ?wsdl is given
if (isset(\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('wsdl'))) {
require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('ter') . 'tx_ter_wsdl.php');
......@@ -65,8 +48,8 @@ class tx_ter_pi1 extends AbstractPlugin
}
try {
$server = new \SoapServer(null, ['uri' => $this->wsdlNamespace, 'trace' => true, 'exceptions' => true]);
$server->setClass(\tx_ter_api::class, $this);
$server = new \SoapServer(null, ['uri' => \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\T3o\Ter\Api\Configuration::class)->getWsdlNamespace(), 'trace' => true, 'exceptions' => true]);
$server->setClass(\tx_ter_api::class);
$server->handle(file_get_contents('php://input'));
// Due to different behaviour on stage and prod server we need this exit to prevent wrong XML response
exit();
......
plugin.tx_ter_pi1 {
pid =
reviewersFrontendUsergroupUid = 2
adminFrontendUsergroupUid = 3
securityTeamFrontendUsergroupUid = 22
wsdlNamespace =
}
# all set in ext_localconf.php to be available at any time
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ namespace T3o\TerFe2\Service;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use T3o\Ter\Api\Configuration;
use T3o\Ter\Exception\InternalServerErrorException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
......@@ -35,9 +36,10 @@ class ExtensionIndexService implements LoggerAwareInterface
public function __construct(string $basePath = null)
{
if ($basePath === null) {
$basePath = $this->getRepositoryBasePath();
$this->basePath = $this->getRepositoryBasePath();
} else {
$this->basePath = rtrim($basePath, '/') . '/';
}
$this->basePath = rtrim($basePath, '/') . '/';
}
/**
......@@ -226,11 +228,6 @@ class ExtensionIndexService implements LoggerAwareInterface
protected function getRepositoryBasePath(): string
{
// Check extension repository path
$extensionConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ter'] ?? [];
if (empty($extensionConfig['repositoryDir'])) {
throw new \Exception('No repository path found in extension configuration', 1303220917);
}
return $extensionConfig['repositoryDir'];
return GeneralUtility::makeInstance(Configuration::class)->getRepositoryBasePath();
}
}
......@@ -30,11 +30,6 @@ class TerService
*/
protected $terApi;
/**
* @var string
*/
public $repositoryDir = '';
/**
* Load TER connection
*
......@@ -47,7 +42,6 @@ class TerService
$this->userData = new \stdClass();
$this->userData->username = $username;
$this->userData->password = $password;
$this->repositoryDir = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ter']['repositoryDir'];
$this->terApi = new \tx_ter_api($this);
}
......
......@@ -10,15 +10,6 @@ plugin.tx_solr.ter_detailpage = 3
# Page ID for website users
styles.content.loginform.pid = 8
# Page ID for the extensions sysfolder
plugin.tx_ter_pi1.pid = 2
# wsdl Namespace for the soap server
plugin.tx_ter_pi1.wsdlNamespace = https://extensions.typo3.org/wsdl/tx_ter/
[applicationContext = Production/Stage]
plugin.tx_ter_pi1.wsdlNamespace = https://extensions-stage.typo3.org/wsdl/tx_ter/
[global]
plugin.tx_solr {
view {
templateRootPath = EXT:ter_layout/Resources/Private/Templates/Solr/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment