Commit 70ac96db authored by Thomas Löffler's avatar Thomas Löffler

Merge branch 'develop' into ci/improve-tests

parents c33a4137 708082a1
Pipeline #10450 failed with stages
in 3 minutes and 14 seconds
......@@ -5,9 +5,8 @@
/**/*.example
/.dbimageBuild
/.dbimageExtra
/.ddev-docker-compose-base.yaml
/.ddev-docker-compose-full.yaml
/.ddevlive-downloads
/.ddev-docker-*.yaml
/.*downloads
/.global_commands
/.homeadditions
/.sshimageBuild
......
......@@ -9,6 +9,7 @@ xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
mariadb_version: "10.3"
mysql_version: ""
provider: default
hooks:
post-import-db:
......@@ -23,12 +24,14 @@ omit_containers: [dba]
webimage_extra_packages: [php7.4-ldap]
use_dns_when_possible: true
timezone: Europe/Berlin
composer_version: "2"
web_environment: []
# This config.yaml was created with ddev version v1.14.2
# webimage: drud/ddev-webserver:v1.14.2
# dbimage: drud/ddev-dbserver-mariadb-10.2:v1.14.1
# dbaimage: phpmyadmin/phpmyadmin:5
# This config.yaml was created with ddev version v1.17.0-alpha3
# webimage: drud/ddev-webserver:20210111_lolautruche_blackfire
# dbimage: drud/ddev-dbserver-mariadb-10.2:switch-to-github-actions
# dbaimage: phpmyadmin:5
# However we do not recommend explicitly wiring these images into the
# config.yaml as they may break future versions of ddev.
# You can update this config.yaml using 'ddev config'.
......@@ -42,7 +45,7 @@ timezone: Europe/Berlin
# docroot: <relative_path> # Relative path to the directory containing index.php.
# php_version: "7.3" # PHP version to use, "5.6", "7.0", "7.1", "7.2", "7.3", "7.4"
# php_version: "7.4" # PHP version to use, "5.6", "7.0", "7.1", "7.2", "7.3", "7.4" "8.0"
# You can explicitly specify the webimage, dbimage, dbaimage lines but this
# is not recommended, as the images are often closely tied to ddev's' behavior,
......@@ -63,10 +66,10 @@ timezone: Europe/Berlin
# xdebug_enabled: false # Set to true to enable xdebug and "ddev start" or "ddev restart"
# Note that for most people the commands
# "ddev exec enable_xdebug" and "ddev exec disable_xdebug" work better,
# "ddev xdebug" to enable xdebug and "ddev xdebug off" to disable it work better,
# as leaving xdebug enabled all the time is a big performance hit.
# webserver_type: nginx-fpm # Can be set to apache-fpm or apache-cgi as well
# webserver_type: nginx-fpm # or apache-fpm
# timezone: Europe/Berlin
# This is the timezone used in the containers and by PHP;
......@@ -74,6 +77,13 @@ timezone: Europe/Berlin
# see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# For example Europe/Dublin or MST7MDT
# composer_version: "2"
# if composer_version:"" it will use the current ddev default composer release.
# It can also be set to "1", to get most recent composer v1
# or "2" for most recent composer v2.
# It can be set to any existing specific composer version.
# After first project 'ddev start' this will not be updated until it changes
# additional_hostnames:
# - somename
# - someothername
......@@ -96,7 +106,7 @@ timezone: Europe/Berlin
# These values specify the destination directory for ddev ssh and the
# directory in which commands passed into ddev exec are run.
# omit_containers: ["db", dba", "ddev-ssh-agent"]
# omit_containers: [db, dba, ddev-ssh-agent]
# Currently only these containers are supported. Some containers can also be
# omitted globally in the ~/.ddev/global_config.yaml. Note that if you omit
# the "db" container, several standard features of ddev that access the
......@@ -106,6 +116,9 @@ timezone: Europe/Berlin
# Great performance improvement but requires host configuration first.
# See https://ddev.readthedocs.io/en/stable/users/performance/#using-nfs-to-mount-the-project-into-the-container
# fail_on_hook_fail: False
# Decide whether 'ddev start' should be interrupted by a failing hook
# host_https_port: "59002"
# The host port binding for https can be explicitly specified. It is
# dynamic unless otherwise specified.
......@@ -130,7 +143,7 @@ timezone: Europe/Berlin
# mailhog_https_port: "8026"
# The MailHog ports can be changed from the default 8025 and 8026
# webimage_extra_packages: [php-yaml, php7.3-ldap]
# webimage_extra_packages: [php7.4-tidy, php-bcmath]
# Extra Debian packages that are needed in the webimage can be added here
# dbimage_extra_packages: [telnet,netcat]
......@@ -157,6 +170,11 @@ timezone: Europe/Berlin
# Drupal's settings.php/settings.ddev.php or TYPO3's AdditionalSettings.php
# In this case the user must provide all such settings.
# You can inject environment variables into the web container with:
# web_environment:
# - SOMEENV=somevalue
# - SOMEOTHERENV=someothervalue
# no_project_mount: false
# (Experimental) If true, ddev will not mount the project into the web container;
# the user is responsible for mounting it manually or via a script.
......
......@@ -16,3 +16,6 @@ services:
- TER_REST_JWT_SUBJECT=t3o-ter-rest
- TER_REST_JWT_LATENCY=60
- TER_REST_SIGNATURE_IDENTIFIER=ecdsa
- SOLR_HOST=solr
- SOLR_PORT=8983
- SOLR_SCHEME=http
......@@ -3,9 +3,9 @@ version: '3.6'
services:
solr:
container_name: ddev-${DDEV_SITENAME}-solr
image: typo3solr/ext-solr:10.0.1
image: typo3solr/ext-solr:11.0.3
restart: "no"
ports:
expose:
- 8983
labels:
com.ddev.site-name: ${DDEV_SITENAME}
......@@ -17,4 +17,4 @@ services:
- "./solr:/opt/solr/server/solr"
web:
links:
- solr:$DDEV_HOSTNAME
- solr
include:
- project: 'services/common/t3o-basic-pipeline-jobs'
- project: 'services/t3o-sites/common/t3o-basic-pipeline-jobs'
ref: main
file: 't3o-basic-pipeline-jobs.yml'
......@@ -65,9 +65,10 @@ test:mutation:
- composer config cache-dir /cache/composer
- mkdir $TYPO3_PATH_WEB/fileadmin/ && touch $TYPO3_PATH_WEB/fileadmin/currentcoredata.json
script:
- composer selfupdate --1
- composer selfupdate --2
- composer install --ignore-platform-reqs
- ./vendor/bin/infection --min-msi=10 --min-covered-msi=75 --threads=4
retry: 2
artifacts:
when: always
paths:
......
......@@ -20,8 +20,7 @@ $sharedFiles = [
set('shared_files', $sharedFiles);
$writeableDirectories = [
'public/typo3temp',
'var'
'public/typo3temp'
];
set('writable_dirs', $writeableDirectories);
......@@ -36,7 +35,10 @@ $exclude = [
'Upgrading.txt',
'README',
'*.example',
'AdditionalConfiguration.sample.php'
'AdditionalConfiguration.sample.php',
'.gitlab-ci',
'.gitlab',
'typoscript-lint.yml'
];
set('rsync', [
'exclude' => array_merge($sharedDirectories, $sharedFiles, $exclude),
......@@ -56,18 +58,11 @@ inventory('./.gitlab-ci/deployer/servers.yml');
set('php', 'php');
set('bin_folder', 'vendor/bin/');
task('typo3', function() {
run('cd {{release_path}} && {{php}} {{bin_folder}}typo3cms install:generatepackagestates');
task('typo3', function () {
run('cd {{release_path}} && {{php}} {{bin_folder}}typo3cms install:extensionsetupifpossible');
run('cd {{release_path}} && {{php}} {{bin_folder}}typo3cms upgrade:prepare -q');
run('cd {{release_path}} && {{php}} {{bin_folder}}typo3cms upgrade:run databaseRowsUpdateWizard pagesLanguageOverlayBeGroupsAccessRights');
});
task('solr:host', function() {
run('cd {{deploy_path}} && ./solr_change_host.sh');
});
task('typo3:ter_wsdl', function() {
task('typo3:ter_wsdl', function () {
run('cd {{release_path}}/public/typo3conf/ext && mkdir ter');
run('cd {{release_path}}/public/typo3conf/ext/ter && ln -s ../../../../private/typo3conf/ext/ter/tx_ter_wsdl.php');
run('cd {{release_path}}/public/typo3conf/ext/ter && ln -s ../../../../private/typo3conf/ext/ter/tx_ter.wsdl');
......@@ -77,6 +72,16 @@ task('cache', function () {
run('cd {{release_path}} && {{php}} {{bin_folder}}cachetool opcache:reset');
});
task('maintenance:activate', function () {
run('echo "return 503;" > ~/cnf/nginx-{{deploy_type}}.conf');
run('sudo /usr/sbin/service php74-extensions-{{deploy_type}} restart');
run('sudo /usr/sbin/service nginx reload');
});
task('maintenance:deactivate', function () {
run('rm ~/cnf/nginx-{{deploy_type}}.conf');
run('sudo /usr/sbin/service php74-extensions-{{deploy_type}} restart');
run('sudo /usr/sbin/service nginx reload');
});
task('deploy', [
'deploy:prepare',
......@@ -85,10 +90,11 @@ task('deploy', [
'rsync',
'deploy:shared',
'deploy:writable',
'maintenance:activate',
'typo3',
'typo3:ter_wsdl',
'deploy:symlink',
'solr:host',
'cache',
'maintenance:deactivate',
'cleanup'
]);
......@@ -6,6 +6,7 @@ main:
forward_agent: true
deploy_path: ~/ci/
keep_releases: 2
deploy_type: prod
develop:
stage: stage
hostname: extensions.typo3.dev
......@@ -14,3 +15,4 @@ develop:
forward_agent: true
deploy_path: ~/ci/
keep_releases: 2
deploy_type: stage
......@@ -17,16 +17,8 @@
"url": "extensions/*"
},
{
"type": "vcs",
"url": "https://git-t3o.typo3.org/t3o/t3olayout.git"
},
{
"type": "vcs",
"url": "https://git-t3o.typo3.org/t3o/gitlab_api.git"
},
{
"type": "vcs",
"url": "https://git-t3o.typo3.org/t3o/test-helpers.git"
"type": "composer",
"url": "https://gitlab.typo3.org/api/v4/group/560/-/packages/composer/"
}
],
"require": {
......@@ -43,10 +35,10 @@
"lcobucci/jwt": "^3.3",
"nimut/testing-framework": "^5.0",
"t3o/t3olayout": "^5.0",
"t3o/ter-frontend": "^0.5.0",
"t3o/ter-layout": "^0.2.0",
"t3o/ter-rest": "^0.1.0",
"t3o/ter-soap": "^2.1",
"t3o/ter-frontend": "@dev",
"t3o/ter-layout": "@dev",
"t3o/ter-rest": "@dev",
"t3o/ter-soap": "@dev",
"typo3/cms-adminpanel": "^10.4",
"typo3/cms-seo": "^10.4"
},
......@@ -62,7 +54,7 @@
"punktde/codeception-database": "^2.0",
"punktde/codeception-filesystem": "^2.0",
"punktde/codeception-webdriver": "^2.2",
"t3o/test-helpers": "dev-master"
"t3o/test-helpers": "dev-main"
},
"config": {
"store-auths": false,
......
This diff is collapsed.
......@@ -33,9 +33,9 @@ errorHandling:
errorContentSource: 't3://page?uid=12'
routes: { }
solr_enabled_read: true
solr_scheme_read: http
solr_host_read: solr
solr_port_read: 8983
solr_scheme_read: '%env(SOLR_SCHEME)%'
solr_host_read: '%env(SOLR_HOST)%'
solr_port_read: '%env(SOLR_PORT)%'
solr_path_read: /solr/
solr_use_write_connection: false
imports:
......
......@@ -18,7 +18,6 @@
"issues": "https://git-t3o.typo3.org/t3o/ter/issues"
},
"license": ["GPL-2.0-or-later"],
"version": "2.2.0",
"require": {
"ext-soap": "*",
"typo3/cms-core": "^9.5 || ^10.4"
......
......@@ -114,7 +114,7 @@ class PackagistCommand extends Command
foreach ($downloadData['package']['downloads']['versions'] as $version => $downloads) {
// To ensure packagist version with "v" in tag also gets counted e.g. v4.2.3 is 4.2.3 in TER.
$version = preg_replace('#v#', '', $version);
$version = ltrim($version, 'v');
$versionFound = $this->versionRepository->findOneByExtensionAndVersionString($extension, $version);
if (null === $versionFound) {
continue;
......
......@@ -83,6 +83,7 @@ class ExtensionController
header('Content-Type: application/json');
echo $json;
exit();
}
}
......
......@@ -54,6 +54,7 @@ class TokenController extends ActionController implements LoggerAwareInterface
$this->view->assignMultiple([
'actions' => self::API_ACTIONS,
'activeTab' => $this->getActiveTab(),
'expires' => strtotime('+7 day', (int)$this->context->getPropertyFromAspect('date', 'timestamp')),
'extensions' => $this->extensionRepository->findByFrontendUser(
(string)$this->context->getPropertyFromAspect('frontend.user', 'username')
)
......
......@@ -81,7 +81,12 @@ class DownloadRepository extends AbstractRepository
*/
public function findDownloadCounterByMonthAndExtensionKey($month, $extensionKey, $versionId, $source)
{
$querySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$query = $this->createQuery();
$query->setQuerySettings($querySettings);
$query->matching(
$query->logicalAnd(
[
......
......@@ -135,7 +135,9 @@ class ExtensionIndexService implements LoggerAwareInterface
$versionObj->appendChild(new \DOMElement('title', $this->xmlentities((string)$extensionVersionArr['title'])));
$versionObj->appendChild(new \DOMElement('description', $this->xmlentities((string)$extensionVersionArr['description'])));
$versionObj->appendChild(new \DOMElement('state', $this->xmlentities((string)$extensionVersionArr['state'])));
$versionObj->appendChild(new \DOMElement('reviewstate', (string)$extensionVersionArr['review_state']));
// Use "0" for outdated extension versions as the Extension Manager handles it as insecure
$reviewState = (string)((int)$extensionVersionArr['review_state'] !== -2 ? $extensionVersionArr['review_state'] : 0);
$versionObj->appendChild(new \DOMElement('reviewstate', $reviewState));
$versionObj->appendChild(new \DOMElement('category', $this->xmlentities((string)$extensionVersionArr['em_category'])));
if ($extensionVersionArr['category'] === 'distribution') {
$prefixDistributionFilePath = $extensionKey[0] . '/' . $extensionKey[1] . '/' . $extensionKey . '_' . $versionNumber . '_';
......
......@@ -27,7 +27,7 @@ use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
class TranslationStatusService
{
/** @var string */
private $statusUrl = 'https://localize.typo3.org/fileadmin/ter/status.json';
private $statusUrl = 'https://localize.typo3.org/xliff/status.json';
/** @var ObjectManager */
private $objectManager;
......
......@@ -25,7 +25,7 @@ use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
*/
class TokenCreationValidator extends AbstractValidator
{
private const MAX_LIFETIME = 8035200;
private const MAX_LIFETIME = 31536000;
private const AVAILABLE_SCOPES = [
'extension:read',
'extension:write',
......
<div class="row">
<div class="col-md-8">
<p>
Enter a name, select the expiration date (max 3 months), the scopes and the extensions for the token.
Enter a name, select the expiration date (max 1 year), the scopes and the extensions for the token.
Approve by entering your password.
</p>
</div>
......@@ -16,7 +16,7 @@
<div class="form-group row">
<div class="col-md-8">
<label for="tokenExpires">Expiration date</label>
<f:form.textfield type="date" class="form-control" id="tokenExpires" property="expires" value="" />
<f:form.textfield type="date" class="form-control" id="tokenExpires" property="expires" value="{expires -> f:format.date(format: 'Y-m-d')}" />
</div>
</div>
<div class="form-group row">
......@@ -83,7 +83,7 @@
</f:if>
<div class="form-group row">
<div class="col-md-8">
<label for="tokenPassword">Your password</label>
<label for="tokenPassword">Your typo3.org password</label>
<f:form.textfield type="password" class="form-control" id="tokenPassword" property="password" value="" required="true" />
</div>
</div>
......
......@@ -15,7 +15,7 @@
</div>
<div class="form-group row">
<div class="col-md-8">
<label for="tokenPassword">Your password</label>
<label for="tokenPassword">Your typo3.org password</label>
<f:form.textfield type="password" class="form-control" id="tokenPassword" property="password" value="" required="true" />
</div>
</div>
......@@ -24,4 +24,4 @@
<f:form.submit class="btn btn-primary mb-0 mt-0" value="Refresh access token" />
</div>
</div>
</f:form>
\ No newline at end of file
</f:form>
......@@ -15,7 +15,7 @@
</div>
<div class="form-group row">
<div class="col-md-8">
<label for="tokenPassword">Your password</label>
<label for="tokenPassword">Your typo3.org password</label>
<f:form.textfield type="password" class="form-control" id="tokenPassword" property="password" value="" required="true" />
</div>
</div>
......@@ -24,4 +24,4 @@
<f:form.submit class="btn btn-primary mb-0 mt-0" value="Revoke access token" />
</div>
</div>
</f:form>
\ No newline at end of file
</f:form>
......@@ -230,7 +230,7 @@
<f:for each="{likedExtensions}" as="extension">
<tr>
<td class="text-middle">
<f:link.action controller="Extension" action="show" arguments="{extension: extension}">{extension.extKey}</f:link.action><br>
<f:link.action pageUid="{settings.pages.extensionDetailPID}" controller="Extension" action="show" arguments="{extension : extension}">{extension.extKey}</f:link.action><br>
{extension.lastVersion.author.name}
</td>
<td>
......
......@@ -20,7 +20,8 @@
<div class="tab-content">
<f:for each="{actions}" as="action">
<div class="tab-pane mt-3 {f:if(condition: '{activeTab} == {action}', then: 'active')}" id="{action}" role="tabpanel">
<f:render partial="Token/{action -> f:format.case(mode: 'capital')}" arguments="{settings: settings, extensions: extensions}" />
<f:render partial="Token/{action -> f:format.case(mode: 'capital')}"
arguments="{settings: settings, expires: expires, extensions: extensions}" />
</div>
</f:for>
</div>
......
......@@ -33,7 +33,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
<title/>
<description/>
<state/>
<reviewstate/>
<reviewstate>0</reviewstate>
<category/>
<downloadcounter/>
<lastuploaddate/>
......@@ -54,7 +54,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
<title/>
<description/>
<state/>
<reviewstate/>
<reviewstate>0</reviewstate>
<category/>
<downloadcounter/>
<lastuploaddate/>
......@@ -75,7 +75,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
<title/>
<description/>
<state/>
<reviewstate/>
<reviewstate>0</reviewstate>
<category/>
<downloadcounter/>
<lastuploaddate/>
......@@ -89,6 +89,48 @@ class ExtensionIndexServiceTest extends UnitTestCase
<t3xfilemd5/>
<documentation_link/>
</version>
</extension>
<extension extensionkey="insecure">
<downloadcounter>131313</downloadcounter>
<version version="2.0.0">
<title/>
<description/>
<state/>
<reviewstate>-1</reviewstate>
<category/>
<downloadcounter/>
<lastuploaddate/>
<uploadcomment/>
<dependencies/>
<composerinfo/>
<authorname/>
<authoremail/>
<authorcompany>Security</authorcompany>
<ownerusername>thomas</ownerusername>
<t3xfilemd5/>
<documentation_link/>
</version>
</extension>
<extension extensionkey="outdated">
<downloadcounter>131313</downloadcounter>
<version version="2.0.0">
<title/>
<description/>
<state/>
<reviewstate>0</reviewstate>
<category/>
<downloadcounter/>
<lastuploaddate/>
<uploadcomment/>
<dependencies/>
<composerinfo/>
<authorname/>
<authoremail/>
<authorcompany>Old</authorcompany>
<ownerusername>thomas</ownerusername>
<t3xfilemd5/>
<documentation_link/>
</version>
</extension>
</extensions>
';
......@@ -100,6 +142,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
'versions' => [
'1.0.0' => [
'authorcompany' => 'ACME',
'review_state' => 0,
'dependencies' => '[{"kind":"depends","extensionKey":"typo3","versionRange":"8.7.0-10.4.99"}]'
]
]
......@@ -110,6 +153,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
'versions' => [
'1.5.0' => [
'authorcompany' => 't3o',
'review_state' => 0,
'dependencies' => '[]'
]
]
......@@ -120,6 +164,29 @@ class ExtensionIndexServiceTest extends UnitTestCase
'versions' => [
'2.0.0' => [
'authorcompany' => 'INC',
'review_state' => 0,
'dependencies' => null
]
]
],
'insecure' => [
'downloads' => 131313,
'frontend_user' => 'thomas',
'versions' => [
'2.0.0' => [
'authorcompany' => 'Security',
'review_state' => -1,
'dependencies' => null
]
]
],
'outdated' => [
'downloads' => 131313,
'frontend_user' => 'thomas',
'versions' => [
'2.0.0' => [
'authorcompany' => 'Old',
'review_state' => -2,
'dependencies' => null
]
]
......@@ -130,7 +197,7 @@ class ExtensionIndexServiceTest extends UnitTestCase
$resultString = $result->saveXML();
// remove the lines with "<!--Index created
$resultString = preg_replace('/\<!--Index created(.*)--\>\n/m', '', $resultString);
self::assertEquals($resultString, $expected);
self::assertEquals($expected, $resultString);
}
/**
......
......@@ -18,7 +18,6 @@
"issues": "https://git-t3o.typo3.org/t3o/ter/issues"
},
"license": ["GPL-2.0-or-later"],
"version": "0.5.0",
"require": {
"ext-json": "*",
"typo3/cms-core": "^9.5 || ^10.4",
......
......@@ -60,7 +60,7 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\T3o\TerFe2\Task