Commit 75dd7858 authored by Matthias Adrowski's avatar Matthias Adrowski
Browse files

[TASK] ECS run

parent 32c87665
......@@ -46,7 +46,6 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
* @package SGalinski\SgRest\Controller
*/
abstract class AbstractRestController extends ActionController {
/**
* @var JsonView
*/
......@@ -179,7 +178,7 @@ abstract class AbstractRestController extends ActionController {
]
);
$this->response->setStatus($exception->getCode() < 1000 ? $exception->getCode(): 500 );
$this->response->setStatus($exception->getCode() < 1000 ? $exception->getCode() : 500);
$this->response->addAdditionalHeaderData($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error');
$this->response->appendContent(json_encode(['message' => $exception->getMessage()]));
}
......@@ -297,5 +296,4 @@ abstract class AbstractRestController extends ActionController {
$this->view->assign('data', $data);
}
}
......@@ -38,7 +38,6 @@ use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
* Class AuthenticationController
*/
class AuthenticationController extends AbstractRestController implements LoggerAwareInterface {
use LoggerAwareTrait;
/**
......@@ -57,7 +56,6 @@ class AuthenticationController extends AbstractRestController implements LoggerA
* Checks if there is a logged in frontend user and gives out a token
*/
public function getBearerTokenAction(): void {
$loggedInUser = $GLOBALS['TSFE']->fe_user->user;
if ($loggedInUser !== NULL) {
......@@ -65,7 +63,6 @@ class AuthenticationController extends AbstractRestController implements LoggerA
// if the user doesn't have permission for any access group, no need for him to get a token
if ($accessGroups !== '') {
$extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('sg_rest');
$expirationTime = $extConf['tokenExpirationTime'];
......@@ -88,7 +85,7 @@ class AuthenticationController extends AbstractRestController implements LoggerA
}
// Clear the session of the logged in user again
if($GLOBALS['TSFE']->fe_user instanceof FrontendUserAuthentication){
if ($GLOBALS['TSFE']->fe_user instanceof FrontendUserAuthentication) {
$GLOBALS['TSFE']->fe_user->removeSessionData();
$GLOBALS['TSFE']->fe_user = NULL;
}
......@@ -105,8 +102,7 @@ class AuthenticationController extends AbstractRestController implements LoggerA
['user' => $loggedInUser]
);
}
} else if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
} elseif ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
$this->logger->log(
LogLevel::ERROR,
'No authenticated user found while trying to retrieve a bearer token.',
......@@ -119,5 +115,4 @@ class AuthenticationController extends AbstractRestController implements LoggerA
403
);
}
}
......@@ -100,5 +100,3 @@ class FrontendUser extends ExtbaseFrontendUser {
$this->testMode = $testMode;
}
}
?>
......@@ -35,7 +35,6 @@ use TYPO3\CMS\Extbase\Domain\Model\FileReference;
* @package SGalinski\SgRest\Events
*/
class BeforeComposeFileReferenceArrayEvent {
/**
* @var FileReference
*/
......
......@@ -44,7 +44,6 @@ use TYPO3\CMS\Core\Http\Response;
* @package SGalinski\SgRest\Middleware
*/
abstract class AbstractRestMiddleware implements LoggerAwareInterface, MiddlewareInterface {
use LoggerAwareTrait;
/**
......@@ -148,8 +147,8 @@ abstract class AbstractRestMiddleware implements LoggerAwareInterface, Middlewar
if (isset($this->pathSegments['entity'])) {
$controllerName .= 'Rest\\' . ucfirst($this->pathSegments['apiKey']) . '\\' . ucfirst(
$this->pathSegments['entity']
);
$this->pathSegments['entity']
);
}
return $controllerName;
......@@ -164,12 +163,14 @@ abstract class AbstractRestMiddleware implements LoggerAwareInterface, Middlewar
protected function getCallableActionName($method): string {
if ($method === 'POST') {
return 'post' . mb_strtoupper(mb_substr($this->pathSegments['verb'], 0, 1)) . mb_substr(
$this->pathSegments['verb'], 1
);
$this->pathSegments['verb'],
1
);
}
return 'get' . mb_strtoupper(mb_substr($this->pathSegments['verb'], 0, 1)) . mb_substr(
$this->pathSegments['verb'], 1
);
$this->pathSegments['verb'],
1
);
}
/**
......
......@@ -42,7 +42,6 @@ use TYPO3\CMS\Core\Utility\HttpUtility;
* @package SGalinski\SgRest\Middleware
*/
class RestAuthenticator extends AbstractRestMiddleware {
/**
* Process an incoming server request.
*
......@@ -56,7 +55,6 @@ class RestAuthenticator extends AbstractRestMiddleware {
* @throws \Exception
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$queryParams = $request->getQueryParams();
if (!isset($queryParams[self::argumentNamespace])) {
......@@ -64,7 +62,9 @@ class RestAuthenticator extends AbstractRestMiddleware {
}
$this->requestSegments = GeneralUtility::trimExplode(
'/', $queryParams[self::argumentNamespace]['request'], TRUE
'/',
$queryParams[self::argumentNamespace]['request'],
TRUE
);
$this->requestHeaders = $request->getHeaders();
......@@ -83,7 +83,8 @@ class RestAuthenticator extends AbstractRestMiddleware {
try {
// @todo: this currently returns a 500 for a permission question?
$httpPermissions = $this->registrationService->getHttpPermissionsForEntity(
$this->pathSegments['entity'], $apiKey
$this->pathSegments['entity'],
$apiKey
);
} catch (\RuntimeException $exception) {
if (in_array($exception->getCode(), $this->reasonableExceptionCodes, TRUE)) {
......@@ -103,11 +104,9 @@ class RestAuthenticator extends AbstractRestMiddleware {
* when the client requests a bearer token, we don't need to do access checks etc. the user verification is done by the AuthServices
*/
if (!($this->pathSegments['entity'] === 'authentication' && $pureActionName === 'getbearertoken' && $httpMethod === 'POST')) {
$authenticated = $this->authenticationService->verifyRequest($this->requestHeaders);
if (!$authenticated) {
if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
$this->logger->log(
LogLevel::ERROR,
......@@ -126,7 +125,6 @@ class RestAuthenticator extends AbstractRestMiddleware {
$verifiedAccess = $this->authenticationService->verifyUserAccess($apiKey);
if (!$verifiedAccess) {
if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
$this->logger->log(
LogLevel::ERROR,
......@@ -140,12 +138,12 @@ class RestAuthenticator extends AbstractRestMiddleware {
}
return $this->createExceptionJsonResponse(
'You tried to access an object where you do not have the necessary permissions.', 403
'You tried to access an object where you do not have the necessary permissions.',
403
);
}
if ($httpMethod === 'DELETE' && $this->pathSegments['verb'] !== '' && !$httpPermissions['deleteForVerbs']) {
if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
$this->logger->log(
LogLevel::ERROR,
......@@ -163,7 +161,8 @@ class RestAuthenticator extends AbstractRestMiddleware {
}
return $this->createExceptionJsonResponse(
'The DELETE method is not permitted for the given path.', 405
'The DELETE method is not permitted for the given path.',
405
);
}
......@@ -172,7 +171,6 @@ class RestAuthenticator extends AbstractRestMiddleware {
($httpMethod === 'PATCH' && $identifier <= 0 && !$httpPermissions['patchWithIdentifier']) ||
($httpMethod === 'POST' && $identifier > 0 && !$httpPermissions['postWithIdentifier'])
) {
if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_rest']['enableLogging'] === 1) {
$this->logger->log(
LogLevel::ERROR,
......@@ -190,7 +188,8 @@ class RestAuthenticator extends AbstractRestMiddleware {
}
return $this->createExceptionJsonResponse(
'The ' . $httpMethod . ' method is not permitted for the given path.', 405
'The ' . $httpMethod . ' method is not permitted for the given path.',
405
);
}
......
......@@ -45,7 +45,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* @package SGalinski\SgRest\Middleware
*/
class RestDispatcher extends AbstractRestMiddleware {
/**
* Process an incoming server request.
*
......@@ -59,7 +58,6 @@ class RestDispatcher extends AbstractRestMiddleware {
* @throws \Exception
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$queryParams = $request->getQueryParams();
if (!isset($queryParams[self::argumentNamespace])) {
......@@ -69,7 +67,9 @@ class RestDispatcher extends AbstractRestMiddleware {
$parsedBody = $request->getParsedBody();
$this->requestSegments = GeneralUtility::trimExplode(
'/', $queryParams[self::argumentNamespace]['request'], TRUE
'/',
$queryParams[self::argumentNamespace]['request'],
TRUE
);
$this->requestHeaders = $request->getHeaders();
......@@ -97,7 +97,7 @@ class RestDispatcher extends AbstractRestMiddleware {
$httpMethod = $request->getMethod();
$actionName = $this->getCallableActionName($httpMethod);
$pureActionName = $this->getActionName();
if($pureActionName === 'getbearertoken'){
if ($pureActionName === 'getbearertoken') {
$actionName = 'getBearerToken';
}
......@@ -162,13 +162,13 @@ class RestDispatcher extends AbstractRestMiddleware {
$queryParams[$pluginNamespace]['vendorName'] = $vendorName;
# Add both cases, with and without apiKey, since we seem to have inconsistencies
# with ususal and bearerToken alls
$queryParams[$pluginNamespace.$apiKey]['controller'] = $controllerName;
$queryParams[$pluginNamespace.$apiKey]['action'] = $actionName;
$queryParams[$pluginNamespace.$apiKey]['format'] = $format;
$queryParams[$pluginNamespace.$apiKey]['extensionName'] = $extensionName;
$queryParams[$pluginNamespace.$apiKey]['extension'] = $extensionName;
$queryParams[$pluginNamespace.$apiKey]['vendor'] = $vendorName;
$queryParams[$pluginNamespace.$apiKey]['vendorName'] = $vendorName;
$queryParams[$pluginNamespace . $apiKey]['controller'] = $controllerName;
$queryParams[$pluginNamespace . $apiKey]['action'] = $actionName;
$queryParams[$pluginNamespace . $apiKey]['format'] = $format;
$queryParams[$pluginNamespace . $apiKey]['extensionName'] = $extensionName;
$queryParams[$pluginNamespace . $apiKey]['extension'] = $extensionName;
$queryParams[$pluginNamespace . $apiKey]['vendor'] = $vendorName;
$queryParams[$pluginNamespace . $apiKey]['vendorName'] = $vendorName;
if ($identifier) {
$queryParams[$pluginNamespace . $apiKey]['identifier'] = $identifier;
......
......@@ -37,7 +37,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* @package SGalinski\SgRest\Service\Authentication
*/
abstract class AbstractAuthenticationService implements AuthenticationServiceInterface, LoggerAwareInterface {
use LoggerAwareTrait;
/**
......
......@@ -32,7 +32,6 @@ namespace SGalinski\SgRest\Service\Authentication;
* @package SGalinski\SgRest\Service\Authentication
*/
interface AuthenticationServiceInterface {
/**
* Tries to authenticate a request with the given request headers
*
......
......@@ -28,8 +28,8 @@ namespace SGalinski\SgRest\Service\Authentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class BasicAuthenticationService
......@@ -37,13 +37,11 @@ use TYPO3\CMS\Core\SingletonInterface;
* @package SGalinski\SgRest\Service\Authentication
*/
class BasicAuthenticationService extends AbstractAuthenticationService implements SingletonInterface {
/**
* @param array $requestHeaders
* @return bool
*/
public function verifyRequest(array $requestHeaders): bool {
if (isset($requestHeaders['authtoken'][0]) && !empty($requestHeaders['authtoken'][0])) {
$authToken = $requestHeaders['authtoken'][0];
return ($authToken !== '' && $this->verifyAuthToken($authToken));
......@@ -59,7 +57,6 @@ class BasicAuthenticationService extends AbstractAuthenticationService implement
* @return boolean
*/
protected function verifyAuthToken($authToken): bool {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('fe_users');
$queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
......@@ -90,7 +87,6 @@ class BasicAuthenticationService extends AbstractAuthenticationService implement
* @throws \Exception
*/
public function generateAndUpdateAuthToken($userId): void {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'fe_users'
);
......
......@@ -41,7 +41,6 @@ use TYPO3\CMS\Extbase\Object\Exception;
* @package SGalinski\SgRest\Service\Authentication
*/
class BearerAuthenticationService extends AbstractAuthenticationService implements SingletonInterface {
/**
* @var BearerTokenService
*/
......@@ -70,11 +69,9 @@ class BearerAuthenticationService extends AbstractAuthenticationService implemen
* @throws Exception
*/
protected function verifyBearerToken($bearerToken): bool {
$verified = $this->bearerTokenService->verifyToken($bearerToken);
if ($verified) {
$decodedToken = $this->bearerTokenService->decodeToken($bearerToken);
if ($decodedToken && $decodedToken->user > 0) {
......
......@@ -26,10 +26,10 @@ namespace SGalinski\SgRest\Service;
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser as ExtbaseFrontendUser;
use DomainException;
use TYPO3\CMS\Core\SingletonInterface;
use \DomainException;
use \UnexpectedValueException;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser as ExtbaseFrontendUser;
use UnexpectedValueException;
/**
* This class handles the JWT / Bearer Token generation and validation for the BearerAuthenticationService
......@@ -39,7 +39,6 @@ use \UnexpectedValueException;
* @package SGalinski\SgRest\Service
*/
class BearerTokenService implements SingletonInterface {
/**
* stores the local private key
* @var string
......@@ -96,7 +95,6 @@ class BearerTokenService implements SingletonInterface {
* @return boolean
*/
public function verifyToken($bearerToken): bool {
if (!empty($bearerToken)) {
$payload = $this->decodeToken($bearerToken, $this->privateKey);
......
......@@ -29,6 +29,7 @@ namespace SGalinski\SgRest\Service;
use Exception;
use SGalinski\SgRest\Events\BeforeComposeFileReferenceArrayEvent;
use SGalinski\SgRest\Utility\PathUtility;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Resource\AbstractFile;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\SingletonInterface;
......@@ -39,14 +40,12 @@ use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
use TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
/**
* The DataResolverService converts the data representations of the REST requests. For instance from objects to array
* or the way around.
*/
class DataResolveService implements SingletonInterface {
/**
*
* @var RegistrationService
......@@ -158,7 +157,6 @@ class DataResolveService implements SingletonInterface {
$properties = $object->_getCleanProperties();
if ($object instanceof FileReference && $identifier) {
$event = new BeforeComposeFileReferenceArrayEvent($object, $this);
$this->eventDispatcher->dispatch($event);
$object = $event->getObject();
......
......@@ -243,7 +243,9 @@ class PaginationService {
*/
protected function buildUrlSegments(array $parameters): string {
$urlSegments = array_map(
fn($value, $key) => $key . '/' . urlencode($value), array_values($parameters), array_keys($parameters)
fn ($value, $key) => $key . '/' . urlencode($value),
array_values($parameters),
array_keys($parameters)
);
return '/' . implode('/', $urlSegments);
}
......
......@@ -59,7 +59,10 @@ class RegistrationService implements SingletonInterface {
* @throws \Exception
*/
public function registerAccessGroup(
$apiKey, $extensionName, $accessGroupName = '', array $entitiesConfiguration = []
$apiKey,
$extensionName,
$accessGroupName = '',
array $entitiesConfiguration = []
): void {
$accessGroup = [];
if ($apiKey === '') {
......@@ -105,7 +108,9 @@ class RegistrationService implements SingletonInterface {
}
$httpPermissions = filter_var_array($httpPermissions, FILTER_VALIDATE_BOOLEAN);
if ($httpPermissions) return $httpPermissions + $defaultHttpPermissions;
if ($httpPermissions) {
return $httpPermissions + $defaultHttpPermissions;
}
return $defaultHttpPermissions;
}
......@@ -128,7 +133,10 @@ class RegistrationService implements SingletonInterface {
}
ExtensionUtility::configurePlugin(
$extensionName, 'Rest' . $apiKey, $controller, $controller
$extensionName,
'Rest' . $apiKey,
$controller,
$controller
);
}
......
......@@ -33,7 +33,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* This class contains methods for usage within the TCA forms.
*/
class TcaProvider implements SingletonInterface {
/**
* The method generate an array for an option list, that contains the registered access groups for the rest api.
*
......@@ -48,7 +47,7 @@ class TcaProvider implements SingletonInterface {
$selectOptions = [];
foreach ($accessGroups as $apiKey => $accessGroup) {
if($accessGroup['accessGroupName'] !== 'Authentication'){
if ($accessGroup['accessGroupName'] !== 'Authentication') {
$selectOptions[] = [
'0' => $accessGroup['accessGroupName'],
'1' => $apiKey
......@@ -59,5 +58,3 @@ class TcaProvider implements SingletonInterface {
$config['items'] = $selectOptions;
}
}
?>
......@@ -39,7 +39,6 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
* This is an utility class for the analysis of the REST request uri-path.
*/
class PathUtility {
/**
* This method analysis the given request segments.
*
......@@ -156,7 +155,10 @@ class PathUtility {
* @throws \Exception
*/
public static function createFileUrl(
AbstractEntity $file, $maximumWidth = '2048', $targetFileExtension = '', $cropVariant = 'default'
AbstractEntity $file,
$maximumWidth = '2048',
$targetFileExtension = '',
$cropVariant = 'default'
): string {
if (!($file instanceof FileReference)) {
return '';
......@@ -193,7 +195,10 @@ class PathUtility {
* @return string
*/
protected static function processFileReference(
CoreFileReference $file, $maximumWidth = '2048', $targetFileExtension = '', $cropVariant = 'default'
CoreFileReference $file,
$maximumWidth = '2048',
$targetFileExtension = '',
$cropVariant = 'default'
): string {
if (\strlen($maximumWidth) <= 0) {
return '';
......
<?php
call_user_func(function($extKey) {
call_user_func(function ($extKey) {
$GLOBALS['TCA']['fe_users']['columns']['usergroup']['exclude'] = TRUE;
$tabLabel = 'LLL:EXT:'. $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tab.rest_authentification';
$tabLabel = 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tab.rest_authentification';
$position = '--div--;' . $tabLabel . ', tx_sgrest_auth_token, tx_sgrest_access_groups, tx_sgrest_test_mode';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('fe_users', $position);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
'fe_users', [
'fe_users',
[
'tx_sgrest_auth_token' => [
'exclude' => TRUE,
'label' => 'LLL:EXT:'. $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_auth_token',
'label' => 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_auth_token',
'config' => [
'type' => 'input',
'size' => 40
......@@ -19,7 +20,7 @@ call_user_func(function($extKey) {
],
'tx_sgrest_access_groups' => [
'exclude' => TRUE,
'label' => 'LLL:EXT:'. $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_access_groups',
'label' => 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_access_groups',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
......@@ -31,7 +32,7 @@ call_user_func(function($extKey) {
],
'tx_sgrest_test_mode' => [
'exclude' => TRUE,
'label' => 'LLL:EXT:'. $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_test_mode',
'label' => 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang_db.xlf:fe_users.tx_sgrest_test_mode',
'config' => [
'type' => 'check',
],
......
<?php
$EM_CONF[$_EXTKEY] = array(
$EM_CONF[$_EXTKEY] = [
'title' => 'REST API basis',
'description' => 'The extension provieds a basis REST environment. New endpoints provides a REST environment, so that other extensions only need to register them.',
'category' => 'misc',
......@@ -9,12 +9,12 @@ $EM_CONF[$_EXTKEY] = array(
'author_company' => 'sgalinski Internet Services',
'state' => 'stable',
'version' => '4.3.2',
'constraints' => array(
'depends' => array(
'constraints' => [
'depends' => [
'typo3' => '^10.4',
),
'conflicts' => array(),
'suggests' => array(),
),
],
'conflicts' => [],
'suggests' => [],
],
'_md5_values_when_last_written' => '',
);
];
......@@ -60,5 +60,6 @@ call_user_func(
]
]
);
}, 'sg_rest'
},
'sg_rest'
);
Supports Markdown
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