mirror of
https://github.com/silverstripe/silverstripe-environmentcheck
synced 2024-09-30 05:09:05 +02:00
Compare commits
100 Commits
2.0.0-beta
...
2
Author | SHA1 | Date | |
---|---|---|---|
|
9881c03c22 | ||
|
e8517ebfb0 | ||
|
28ca036345 | ||
|
16caad30b2 | ||
|
6f6c30bdcc | ||
|
f918209e35 | ||
|
714de64252 | ||
|
d9d245a0da | ||
|
9d5f8fce7d | ||
|
f12698f47f | ||
|
6f0d1c84f2 | ||
|
15a8bca241 | ||
|
94ff5b621c | ||
|
0e4867f736 | ||
|
7e59b7e88b | ||
|
e4b8934148 | ||
|
737ac0d8ed | ||
|
3378dc7a99 | ||
|
58caa67c96 | ||
|
7be4c0dbf3 | ||
|
7ba4acc4b2 | ||
|
a76c3b89ea | ||
|
7f6c03b0cb | ||
|
3e3907d14c | ||
|
d3d20e5539 | ||
|
b7554a5fc9 | ||
|
cb13f4ec12 | ||
|
3902a1d688 | ||
|
aa1311fa01 | ||
|
47b184df5d | ||
|
94fa4ee1f0 | ||
|
3f2fbdaea0 | ||
|
05dd7bc0a7 | ||
|
f6e001bf55 | ||
|
e5b77ff325 | ||
|
029078d157 | ||
|
f14fe7c40d | ||
|
585b6564b2 | ||
|
dd037c8f50 | ||
|
d29a062562 | ||
|
2c4d32af6b | ||
|
7c0b7b0ca7 | ||
|
b765ec87c1 | ||
|
56dab108c9 | ||
|
b01567767c | ||
|
e19e476cf4 | ||
|
dfd9c15d56 | ||
|
23104b77aa | ||
|
1aa18e7ced | ||
|
08409bb9ca | ||
|
b2f6e06795 | ||
|
0685dfad75 | ||
|
5f2591a5c1 | ||
|
2bbebc321e | ||
|
9829476dae | ||
|
49d7d5f2a3 | ||
|
f347d1d5c0 | ||
|
c490c4e5a5 | ||
|
d8452c681a | ||
|
e757c9477c | ||
|
6fe0b1889e | ||
|
40050e9ab4 | ||
|
efd996d618 | ||
|
922d810a3a | ||
|
a54400681f | ||
|
c5783a2450 | ||
|
da9eddc0e1 | ||
|
8f7f8570f2 | ||
|
578c73e6ce | ||
|
128ddb56ed | ||
|
ace6c51aae | ||
|
540710ab0f | ||
|
2674beb94a | ||
|
90f0556ca4 | ||
|
27994e51fa | ||
|
986bc370b9 | ||
|
c1bfd5640d | ||
|
df59195634 | ||
|
f74c371e16 | ||
|
41763c6042 | ||
|
f8d35639a0 | ||
|
e323674adf | ||
|
da6a8a8ee4 | ||
|
9940c5e8ab | ||
|
1771a6ef11 | ||
|
05ac221c2f | ||
|
ed61c6bb3a | ||
|
014c23804f | ||
|
f6652c2b37 | ||
|
161f0aefaf | ||
|
a788b37de5 | ||
|
449a265301 | ||
|
7ad2334f49 | ||
|
250c8d2e00 | ||
|
e5651c429c | ||
|
564936ee01 | ||
|
b89aefaa20 | ||
|
152c11638b | ||
|
e6e5ac96df | ||
|
b78c2af4aa |
11
.github/workflows/ci.yml
vendored
Normal file
11
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: CI
|
||||||
|
uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1
|
16
.github/workflows/dispatch-ci.yml
vendored
Normal file
16
.github/workflows/dispatch-ci.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: Dispatch CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
# At 1:20 PM UTC, only on Wednesday and Thursday
|
||||||
|
schedule:
|
||||||
|
- cron: '20 13 * * 3,4'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dispatch-ci:
|
||||||
|
name: Dispatch CI
|
||||||
|
# Only run cron on the silverstripe account
|
||||||
|
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Dispatch CI
|
||||||
|
uses: silverstripe/gha-dispatch-ci@v1
|
17
.github/workflows/keepalive.yml
vendored
Normal file
17
.github/workflows/keepalive.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: Keepalive
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
# The 4th of every month at 10:50am UTC
|
||||||
|
schedule:
|
||||||
|
- cron: '50 10 4 * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
keepalive:
|
||||||
|
name: Keepalive
|
||||||
|
# Only run cron on the silverstripe account
|
||||||
|
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Keepalive
|
||||||
|
uses: silverstripe/gha-keepalive@v1
|
@ -1,9 +0,0 @@
|
|||||||
inherit: true
|
|
||||||
|
|
||||||
checks:
|
|
||||||
php:
|
|
||||||
code_rating: true
|
|
||||||
duplication: true
|
|
||||||
|
|
||||||
filter:
|
|
||||||
paths: [src/*, tests/*]
|
|
33
.travis.yml
33
.travis.yml
@ -1,33 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- COMPOSER_ROOT_VERSION="2.0.x-dev"
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- php: 5.6
|
|
||||||
env: DB=MYSQL PHPCS_TEST=1 PHPUNIT_TEST=1
|
|
||||||
- php: 7.0
|
|
||||||
env: DB=PGSQL PHPUNIT_TEST=1
|
|
||||||
- php: 7.1
|
|
||||||
env: DB=MYSQL PHPUNIT_COVERAGE_TEST=1
|
|
||||||
- php: 7.2
|
|
||||||
env: DB=MYSQL PHPUNIT_TEST=1
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- phpenv rehash
|
|
||||||
- phpenv config-rm xdebug.ini
|
|
||||||
|
|
||||||
- composer validate
|
|
||||||
- composer require --no-update silverstripe/recipe-core:1.0.x-dev
|
|
||||||
- if [[ $DB == PGSQL ]]; then composer require --no-update silverstripe/postgresql:2.0.x-dev; fi
|
|
||||||
- composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit; fi
|
|
||||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi
|
|
||||||
- if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs src/ tests/ *.php; fi
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml; fi
|
|
@ -1,10 +1,7 @@
|
|||||||
# SilverStripe Environment Checker Module
|
# Silverstripe Environment Checker Module
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/silverstripe/silverstripe-environmentcheck.svg?branch=master)](https://travis-ci.org/silverstripe/silverstripe-environmentcheck)
|
[![CI](https://github.com/silverstripe/silverstripe-environmentcheck/actions/workflows/ci.yml/badge.svg)](https://github.com/silverstripe/silverstripe-environmentcheck/actions/workflows/ci.yml)
|
||||||
[![Code Quality](https://scrutinizer-ci.com/g/silverstripe/silverstripe-environmentcheck/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/silverstripe/silverstripe-environmentcheck/?branch=master)
|
[![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
|
||||||
[![Code Coverage](https://codecov.io/gh/silverstripe/silverstripe-environmentcheck/branch/master/graph/badge.svg)](https://codecov.io/gh/silverstripe/silverstripe-environmentcheck)
|
|
||||||
[![Version](http://img.shields.io/packagist/v/silverstripe/environmentcheck.svg?style=flat-square)](https://packagist.org/packages/silverstripe/environmentcheck)
|
|
||||||
[![License](http://img.shields.io/packagist/l/silverstripe/environmentcheck.svg?style=flat-square)](LICENSE.md)
|
|
||||||
|
|
||||||
This module adds an API for running environment checks to your API.
|
This module adds an API for running environment checks to your API.
|
||||||
|
|
||||||
@ -14,10 +11,10 @@ This module adds an API for running environment checks to your API.
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* SilverStripe 4.x
|
* Silverstripe 4.x
|
||||||
* PHP 5.6+
|
* PHP 7.3
|
||||||
|
|
||||||
For SilverStripe 3.x support, please use a `1.x` tagged release.
|
For Silverstripe 3.x support, please use a `1.x` tagged release.
|
||||||
|
|
||||||
## Aren't these just unit tests?
|
## Aren't these just unit tests?
|
||||||
|
|
||||||
@ -85,12 +82,17 @@ SilverStripe\EnvironmentCheck\EnvironmentCheckSuite:
|
|||||||
* `HasClassCheck`: Check that the given class exists.
|
* `HasClassCheck`: Check that the given class exists.
|
||||||
This can be used to check that PHP modules or features are installed.
|
This can be used to check that PHP modules or features are installed.
|
||||||
* `FileWriteableCheck`: Check that the given file is writeable.
|
* `FileWriteableCheck`: Check that the given file is writeable.
|
||||||
|
* `FileAccessibilityAndValidationCheck`: Check that a given file is accessible and optionally matches a given format.
|
||||||
* `FileAgeCheck`: Checks for the maximum age of one or more files or folders.
|
* `FileAgeCheck`: Checks for the maximum age of one or more files or folders.
|
||||||
Useful for files which should be frequently auto-generated,
|
Useful for files which should be frequently auto-generated,
|
||||||
like static caches, as well as for backup files and folders.
|
like static caches, as well as for backup files and folders.
|
||||||
* `ExternalURLCheck`: Checks that one or more URLs are reachable via HTTP.
|
* `ExternalURLCheck`: Checks that one or more URLs are reachable via HTTP.
|
||||||
* `SMTPConnectCheck`: Checks if the SMTP connection configured through PHP.ini works as expected.
|
* `SMTPConnectCheck`: Checks if the SMTP connection configured through PHP.ini works as expected.
|
||||||
* `SolrIndexCheck`: Checks if the Solr cores of given class are available.
|
* `SolrIndexCheck`: Checks if the Solr cores of given class are available.
|
||||||
|
* `SessionCheck`: Checks that a given URL does not generate a session.
|
||||||
|
* `CacheHeadersCheck`: Check cache headers in response for directives that must either be included or excluded as well
|
||||||
|
checking for existence of ETag.
|
||||||
|
* `EnvTypeCheck`: Checks environment type, dev and test should not be used on production environments.
|
||||||
|
|
||||||
## Monitoring Checks
|
## Monitoring Checks
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ SilverStripe\EnvironmentCheck\EnvironmentChecker:
|
|||||||
from_email_address: admin@test.com
|
from_email_address: admin@test.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Errors can be logged via the standard SilverStripe PSR-3 compatible logging. Each check will cause an individual log
|
Errors can be logged via the standard Silverstripe PSR-3 compatible logging. Each check will cause an individual log
|
||||||
entry. You can choose to enable logging separately for warnings and errors, identified through the
|
entry. You can choose to enable logging separately for warnings and errors, identified through the
|
||||||
result of `EnvironmentCheck->check()`.
|
result of `EnvironmentCheck->check()`.
|
||||||
|
|
@ -2,8 +2,12 @@
|
|||||||
Name: environmentcheckinjector
|
Name: environmentcheckinjector
|
||||||
---
|
---
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
CacheHeadersCheck:
|
||||||
|
class: SilverStripe\EnvironmentCheck\Checks\CacheHeadersCheck
|
||||||
DatabaseCheck:
|
DatabaseCheck:
|
||||||
class: SilverStripe\EnvironmentCheck\Checks\DatabaseCheck
|
class: SilverStripe\EnvironmentCheck\Checks\DatabaseCheck
|
||||||
|
EnvTypeCheck:
|
||||||
|
class: SilverStripe\EnvironmentCheck\Checks\EnvTypeCheck
|
||||||
ExternalURLCheck:
|
ExternalURLCheck:
|
||||||
class: SilverStripe\EnvironmentCheck\Checks\ExternalURLCheck
|
class: SilverStripe\EnvironmentCheck\Checks\ExternalURLCheck
|
||||||
FileAccessibilityAndValidationCheck:
|
FileAccessibilityAndValidationCheck:
|
||||||
@ -22,3 +26,14 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
class: SilverStripe\EnvironmentCheck\Checks\SolrIndexCheck
|
class: SilverStripe\EnvironmentCheck\Checks\SolrIndexCheck
|
||||||
URLCheck:
|
URLCheck:
|
||||||
class: SilverStripe\EnvironmentCheck\Checks\URLCheck
|
class: SilverStripe\EnvironmentCheck\Checks\URLCheck
|
||||||
|
EnvCheckClient:
|
||||||
|
factory: 'SilverStripe\EnvironmentCheck\Services\ClientFactory'
|
||||||
|
constructor:
|
||||||
|
timeout: 10.0
|
||||||
|
|
||||||
|
SilverStripe\EnvironmentCheck\Checks\SessionCheck:
|
||||||
|
dependencies:
|
||||||
|
client: '%$EnvCheckClient'
|
||||||
|
SilverStripe\EnvironmentCheck\Checks\CacheHeadersCheck:
|
||||||
|
dependencies:
|
||||||
|
client: '%$EnvCheckClient'
|
||||||
|
@ -12,3 +12,14 @@ SilverStripe\Dev\DevelopmentAdmin:
|
|||||||
controller: Silverstripe\EnvironmentCheck\Controllers\DevCheckController
|
controller: Silverstripe\EnvironmentCheck\Controllers\DevCheckController
|
||||||
links:
|
links:
|
||||||
check: 'Run registered environment checks and display their status'
|
check: 'Run registered environment checks and display their status'
|
||||||
|
|
||||||
|
---
|
||||||
|
Name: environmentcheckroutes-dev_urls-confirmation-exceptions
|
||||||
|
After:
|
||||||
|
- 'dev_urls-confirmation-middleware'
|
||||||
|
---
|
||||||
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
DevUrlsConfirmationMiddleware:
|
||||||
|
properties:
|
||||||
|
Bypasses:
|
||||||
|
- '%$SilverStripe\Control\Middleware\ConfirmationMiddleware\UrlPathStartsWith("dev/check")'
|
||||||
|
12
changelog.md
12
changelog.md
@ -4,7 +4,17 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [2.0.0] - unreleased
|
## [2.1.0]
|
||||||
|
|
||||||
|
* Add new checks:
|
||||||
|
* Environment type
|
||||||
|
* Session
|
||||||
|
* Cache Headers
|
||||||
|
* Fix basic auth
|
||||||
|
* Add unit tests
|
||||||
|
* PSR-2 Conformance
|
||||||
|
|
||||||
|
## [2.0.0]
|
||||||
|
|
||||||
* Minimum versions required:
|
* Minimum versions required:
|
||||||
* SilverStripe 4.x
|
* SilverStripe 4.x
|
||||||
|
@ -3,7 +3,12 @@
|
|||||||
"description": "Provides an API for building environment tests",
|
"description": "Provides an API for building environment tests",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"type": "silverstripe-vendormodule",
|
"type": "silverstripe-vendormodule",
|
||||||
"keywords": ["silverstripe", "testing", "environment", "check"],
|
"keywords": [
|
||||||
|
"silverstripe",
|
||||||
|
"testing",
|
||||||
|
"environment",
|
||||||
|
"check"
|
||||||
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Will Rossiter",
|
"name": "Will Rossiter",
|
||||||
@ -15,18 +20,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"silverstripe/framework": "^4.0",
|
"php": "^7.4 || ^8.0",
|
||||||
"silverstripe/versioned": "^1.0"
|
"silverstripe/framework": "^4.10",
|
||||||
|
"silverstripe/versioned": "^1.0",
|
||||||
|
"guzzlehttp/guzzle": "^6.3.3 || ^7"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^5.7",
|
"phpunit/phpunit": "^9.5",
|
||||||
"squizlabs/php_codesniffer": "^3.0"
|
"squizlabs/php_codesniffer": "^3.0"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": [],
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "2.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"SilverStripe\\EnvironmentCheck\\": "src/",
|
"SilverStripe\\EnvironmentCheck\\": "src/",
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
<ruleset name="SilverStripe">
|
<ruleset name="SilverStripe">
|
||||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||||
|
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
|
|
||||||
<rule ref="PSR2" >
|
<rule ref="PSR2" >
|
||||||
<!-- Current exclusions -->
|
<!-- Current exclusions -->
|
||||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
|
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
|
||||||
|
|
||||||
|
<testsuites>
|
||||||
<testsuite name="Default">
|
<testsuite name="Default">
|
||||||
<directory>tests</directory>
|
<directory>tests</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
<whitelist addUncoveredFilesFromWhitelist="true">
|
<whitelist addUncoveredFilesFromWhitelist="true">
|
||||||
|
207
src/Checks/CacheHeadersCheck.php
Normal file
207
src/Checks/CacheHeadersCheck.php
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Checks;
|
||||||
|
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Control\Controller;
|
||||||
|
use SilverStripe\ORM\ValidationResult;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use SilverStripe\Core\Config\Configurable;
|
||||||
|
use SilverStripe\EnvironmentCheck\Traits\Fetcher;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check cache headers for any response, can specify directives that must be included and
|
||||||
|
* also must be excluded from Cache-Control headers in response. Also checks for
|
||||||
|
* existence of ETag.
|
||||||
|
*
|
||||||
|
* @example SilverStripe\EnvironmentCheck\Checks\CacheHeadersCheck("/",["must-revalidate", "max-age=120"],["no-store"])
|
||||||
|
* @package environmentcheck
|
||||||
|
*/
|
||||||
|
class CacheHeadersCheck implements EnvironmentCheck
|
||||||
|
{
|
||||||
|
use Fetcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings that must be included in the Cache-Control header
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $mustInclude = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings that must be excluded in the Cache-Control header
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $mustExclude = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result to keep track of status and messages for all checks, reuses
|
||||||
|
* ValidationResult for convenience.
|
||||||
|
*
|
||||||
|
* @var ValidationResult
|
||||||
|
*/
|
||||||
|
protected $result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up with URL, arrays of header settings to check.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param array $mustInclude Settings that must be included in Cache-Control
|
||||||
|
* @param array $mustExclude Settings that must be excluded in Cache-Control
|
||||||
|
*/
|
||||||
|
public function __construct($url = '', $mustInclude = [], $mustExclude = [])
|
||||||
|
{
|
||||||
|
$this->setURL($url);
|
||||||
|
$this->mustInclude = $mustInclude;
|
||||||
|
$this->mustExclude = $mustExclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that correct caching headers are present.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
// Using a validation result to capture messages
|
||||||
|
$this->result = new ValidationResult();
|
||||||
|
|
||||||
|
$response = $this->client->get($this->getURL());
|
||||||
|
$fullURL = $this->getURL();
|
||||||
|
if ($response === null) {
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::ERROR,
|
||||||
|
"Cache headers check request failed for $fullURL",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check that Etag exists
|
||||||
|
$this->checkEtag($response);
|
||||||
|
|
||||||
|
// Check Cache-Control settings
|
||||||
|
$this->checkCacheControl($response);
|
||||||
|
|
||||||
|
if ($this->result->isValid()) {
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::OK,
|
||||||
|
$this->getMessage(),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// @todo Ability to return a warning
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::ERROR,
|
||||||
|
$this->getMessage(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collate messages from ValidationResult so that it is clear which parts
|
||||||
|
* of the check passed and which failed.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getMessage()
|
||||||
|
{
|
||||||
|
$ret = '';
|
||||||
|
// Filter good messages
|
||||||
|
$goodTypes = [ValidationResult::TYPE_GOOD, ValidationResult::TYPE_INFO];
|
||||||
|
$good = array_filter(
|
||||||
|
$this->result->getMessages() ?? [],
|
||||||
|
function ($val, $key) use ($goodTypes) {
|
||||||
|
if (in_array($val['messageType'], $goodTypes ?? [])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
ARRAY_FILTER_USE_BOTH
|
||||||
|
);
|
||||||
|
if (!empty($good)) {
|
||||||
|
$ret .= "GOOD: " . implode('; ', array_column($good ?? [], 'message')) . " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter bad messages
|
||||||
|
$badTypes = [ValidationResult::TYPE_ERROR, ValidationResult::TYPE_WARNING];
|
||||||
|
$bad = array_filter(
|
||||||
|
$this->result->getMessages() ?? [],
|
||||||
|
function ($val, $key) use ($badTypes) {
|
||||||
|
if (in_array($val['messageType'], $badTypes ?? [])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
ARRAY_FILTER_USE_BOTH
|
||||||
|
);
|
||||||
|
if (!empty($bad)) {
|
||||||
|
$ret .= "BAD: " . implode('; ', array_column($bad ?? [], 'message'));
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that ETag header exists
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function checkEtag(ResponseInterface $response)
|
||||||
|
{
|
||||||
|
$eTag = $response->getHeaderLine('ETag');
|
||||||
|
$fullURL = Controller::join_links(Director::absoluteBaseURL(), $this->url);
|
||||||
|
|
||||||
|
if ($eTag) {
|
||||||
|
$this->result->addMessage(
|
||||||
|
"$fullURL includes an Etag header in response",
|
||||||
|
ValidationResult::TYPE_GOOD
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->result->addError(
|
||||||
|
"$fullURL is missing an Etag header",
|
||||||
|
ValidationResult::TYPE_WARNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the correct header settings are either included or excluded.
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function checkCacheControl(ResponseInterface $response)
|
||||||
|
{
|
||||||
|
$cacheControl = $response->getHeaderLine('Cache-Control');
|
||||||
|
$vals = array_map('trim', explode(',', $cacheControl ?? ''));
|
||||||
|
$fullURL = Controller::join_links(Director::absoluteBaseURL(), $this->url);
|
||||||
|
|
||||||
|
// All entries from must contain should be present
|
||||||
|
if ($this->mustInclude == array_intersect($this->mustInclude ?? [], $vals)) {
|
||||||
|
$matched = implode(",", $this->mustInclude);
|
||||||
|
$this->result->addMessage(
|
||||||
|
"$fullURL includes all settings: {$matched}",
|
||||||
|
ValidationResult::TYPE_GOOD
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$missing = implode(",", array_diff($this->mustInclude ?? [], $vals));
|
||||||
|
$this->result->addError(
|
||||||
|
"$fullURL is excluding some settings: {$missing}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All entries from must exclude should not be present
|
||||||
|
if (empty(array_intersect($this->mustExclude ?? [], $vals))) {
|
||||||
|
$missing = implode(",", $this->mustExclude);
|
||||||
|
$this->result->addMessage(
|
||||||
|
"$fullURL excludes all settings: {$missing}",
|
||||||
|
ValidationResult::TYPE_GOOD
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$matched = implode(",", array_intersect($this->mustExclude ?? [], $vals));
|
||||||
|
$this->result->addError(
|
||||||
|
"$fullURL is including some settings: {$matched}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/Checks/EnvTypeCheck.php
Normal file
40
src/Checks/EnvTypeCheck.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Checks;
|
||||||
|
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the environment setting is safe. Useful for live sites where a
|
||||||
|
* non "Live" setting might disclose sensitive information.
|
||||||
|
*
|
||||||
|
* @package environmentcheck
|
||||||
|
*/
|
||||||
|
class EnvTypeCheck implements EnvironmentCheck
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check the environment setting.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
$envSetting = Director::get_environment_type();
|
||||||
|
switch ($envSetting) {
|
||||||
|
case 'live':
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::OK,
|
||||||
|
"Env setting is 'live'",
|
||||||
|
];
|
||||||
|
// Fallthrough
|
||||||
|
default:
|
||||||
|
case 'dev':
|
||||||
|
case 'test':
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::ERROR,
|
||||||
|
"Env setting is '{$envSetting}' and may disclose information",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,7 @@ class ExternalURLCheck implements EnvironmentCheck
|
|||||||
public function __construct($urls, $timeout = 15)
|
public function __construct($urls, $timeout = 15)
|
||||||
{
|
{
|
||||||
if ($urls) {
|
if ($urls) {
|
||||||
$this->urls = explode(' ', $urls);
|
$this->urls = explode(' ', $urls ?? '');
|
||||||
}
|
}
|
||||||
$this->timeout = $timeout;
|
$this->timeout = $timeout;
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ class ExternalURLCheck implements EnvironmentCheck
|
|||||||
foreach ($urls as $url) {
|
foreach ($urls as $url) {
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
$chs[] = $ch;
|
$chs[] = $ch;
|
||||||
curl_setopt_array($ch, $this->getCurlOpts($url));
|
curl_setopt_array($ch, $this->getCurlOpts($url) ?? []);
|
||||||
}
|
}
|
||||||
// Parallel execution for faster performance
|
// Parallel execution for faster performance
|
||||||
$mh = curl_multi_init();
|
$mh = curl_multi_init();
|
||||||
|
@ -96,7 +96,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
|||||||
$files = $this->getFiles();
|
$files = $this->getFiles();
|
||||||
if ($files) {
|
if ($files) {
|
||||||
$fileTypeValidateFunc = $this->fileTypeValidateFunc;
|
$fileTypeValidateFunc = $this->fileTypeValidateFunc;
|
||||||
if (method_exists($this, $fileTypeValidateFunc)) {
|
if (method_exists($this, $fileTypeValidateFunc ?? '')) {
|
||||||
$invalidFiles = [];
|
$invalidFiles = [];
|
||||||
$validFiles = [];
|
$validFiles = [];
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If at least one file was valid, count as passed
|
// If at least one file was valid, count as passed
|
||||||
if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) {
|
if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles ?? []) < count($files ?? [])) {
|
||||||
$validFileList = PHP_EOL;
|
$validFileList = PHP_EOL;
|
||||||
foreach ($validFiles as $vf) {
|
foreach ($validFiles as $vf) {
|
||||||
$validFileList .= $vf . PHP_EOL;
|
$validFileList .= $vf . PHP_EOL;
|
||||||
@ -130,7 +130,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (count($invalidFiles) == 0) {
|
if (count($invalidFiles ?? []) == 0) {
|
||||||
$checkReturn = [EnvironmentCheck::OK, 'All files valideted'];
|
$checkReturn = [EnvironmentCheck::OK, 'All files valideted'];
|
||||||
} else {
|
} else {
|
||||||
$invalidFileList = PHP_EOL;
|
$invalidFileList = PHP_EOL;
|
||||||
@ -180,7 +180,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
private function jsonValidate($file)
|
private function jsonValidate($file)
|
||||||
{
|
{
|
||||||
$json = json_decode(file_get_contents($file));
|
$json = json_decode(file_get_contents($file ?? '') ?? '');
|
||||||
if (!$json) {
|
if (!$json) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -204,6 +204,6 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
protected function getFiles()
|
protected function getFiles()
|
||||||
{
|
{
|
||||||
return glob($this->path);
|
return glob($this->path ?? '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ class FileAgeCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
public function check()
|
public function check()
|
||||||
{
|
{
|
||||||
$cutoffTime = strtotime($this->relativeAge, DBDatetime::now()->Format('U'));
|
$cutoffTime = strtotime($this->relativeAge ?? '', DBDatetime::now()->Format('U'));
|
||||||
$files = $this->getFiles();
|
$files = $this->getFiles();
|
||||||
$invalidFiles = [];
|
$invalidFiles = [];
|
||||||
$validFiles = [];
|
$validFiles = [];
|
||||||
@ -127,10 +127,10 @@ class FileAgeCheck implements EnvironmentCheck
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If at least one file was valid, count as passed
|
// If at least one file was valid, count as passed
|
||||||
if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) {
|
if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles ?? []) < count($files ?? [])) {
|
||||||
return [EnvironmentCheck::OK, ''];
|
return [EnvironmentCheck::OK, ''];
|
||||||
}
|
}
|
||||||
if (count($invalidFiles) == 0) {
|
if (count($invalidFiles ?? []) == 0) {
|
||||||
return [EnvironmentCheck::OK, ''];
|
return [EnvironmentCheck::OK, ''];
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
@ -146,6 +146,6 @@ class FileAgeCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
protected function getFiles()
|
protected function getFiles()
|
||||||
{
|
{
|
||||||
return glob($this->path);
|
return glob($this->path ?? '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,22 +34,22 @@ class FileWriteableCheck implements EnvironmentCheck
|
|||||||
if ($this->path[0] == '/') {
|
if ($this->path[0] == '/') {
|
||||||
$filename = $this->path;
|
$filename = $this->path;
|
||||||
} else {
|
} else {
|
||||||
$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $this->path);
|
$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $this->path ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
if (file_exists($filename ?? '')) {
|
||||||
$isWriteable = is_writeable($filename);
|
$isWriteable = is_writeable($filename ?? '');
|
||||||
} else {
|
} else {
|
||||||
$isWriteable = is_writeable(dirname($filename));
|
$isWriteable = is_writeable(dirname($filename ?? ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$isWriteable) {
|
if (!$isWriteable) {
|
||||||
if (function_exists('posix_getgroups')) {
|
if (function_exists('posix_getgroups')) {
|
||||||
$userID = posix_geteuid();
|
$userID = posix_geteuid();
|
||||||
$user = posix_getpwuid($userID);
|
$user = posix_getpwuid($userID ?? 0);
|
||||||
|
|
||||||
$currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename));
|
$currentOwnerID = fileowner(file_exists($filename ?? '') ? $filename : dirname($filename ?? ''));
|
||||||
$currentOwner = posix_getpwuid($currentOwnerID);
|
$currentOwner = posix_getpwuid($currentOwnerID ?? 0);
|
||||||
|
|
||||||
$message = "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe file is "
|
$message = "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe file is "
|
||||||
. "currently owned by '$currentOwner[name]'. ";
|
. "currently owned by '$currentOwner[name]'. ";
|
||||||
@ -60,8 +60,8 @@ class FileWriteableCheck implements EnvironmentCheck
|
|||||||
$groups = posix_getgroups();
|
$groups = posix_getgroups();
|
||||||
$groupList = [];
|
$groupList = [];
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
$groupInfo = posix_getgrgid($group);
|
$groupInfo = posix_getgrgid($group ?? 0);
|
||||||
if (in_array($currentOwner['name'], $groupInfo['members'])) {
|
if (in_array($currentOwner['name'], $groupInfo['members'] ?? [])) {
|
||||||
$groupList[] = $groupInfo['name'];
|
$groupList[] = $groupInfo['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class HasClassCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
public function check()
|
public function check()
|
||||||
{
|
{
|
||||||
if (class_exists($this->className)) {
|
if (class_exists($this->className ?? '')) {
|
||||||
return [EnvironmentCheck::OK, 'Class ' . $this->className.' exists'];
|
return [EnvironmentCheck::OK, 'Class ' . $this->className.' exists'];
|
||||||
}
|
}
|
||||||
return [EnvironmentCheck::ERROR, 'Class ' . $this->className.' doesn\'t exist'];
|
return [EnvironmentCheck::ERROR, 'Class ' . $this->className.' doesn\'t exist'];
|
||||||
|
@ -31,7 +31,7 @@ class HasFunctionCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
public function check()
|
public function check()
|
||||||
{
|
{
|
||||||
if (function_exists($this->functionName)) {
|
if (function_exists($this->functionName ?? '')) {
|
||||||
return [EnvironmentCheck::OK, $this->functionName . '() exists'];
|
return [EnvironmentCheck::OK, $this->functionName . '() exists'];
|
||||||
}
|
}
|
||||||
return [EnvironmentCheck::ERROR, $this->functionName . '() doesn\'t exist'];
|
return [EnvironmentCheck::ERROR, $this->functionName . '() doesn\'t exist'];
|
||||||
|
@ -57,7 +57,7 @@ class SMTPConnectCheck implements EnvironmentCheck
|
|||||||
*/
|
*/
|
||||||
public function check()
|
public function check()
|
||||||
{
|
{
|
||||||
$f = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
|
$f = @fsockopen($this->host ?? '', $this->port ?? 0, $errno, $errstr, $this->timeout);
|
||||||
if (!$f) {
|
if (!$f) {
|
||||||
return [
|
return [
|
||||||
EnvironmentCheck::ERROR,
|
EnvironmentCheck::ERROR,
|
||||||
@ -67,7 +67,7 @@ class SMTPConnectCheck implements EnvironmentCheck
|
|||||||
|
|
||||||
fwrite($f, "HELO its_me\r\n");
|
fwrite($f, "HELO its_me\r\n");
|
||||||
$response = fread($f, 26);
|
$response = fread($f, 26);
|
||||||
if (substr($response, 0, 3) != '220') {
|
if (substr($response ?? '', 0, 3) != '220') {
|
||||||
return [
|
return [
|
||||||
EnvironmentCheck::ERROR,
|
EnvironmentCheck::ERROR,
|
||||||
sprintf('Invalid mail server response: %s', $response)
|
sprintf('Invalid mail server response: %s', $response)
|
||||||
|
71
src/Checks/SessionCheck.php
Normal file
71
src/Checks/SessionCheck.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Checks;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use SilverStripe\EnvironmentCheck\Traits\Fetcher;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that a given URL does not generate a session.
|
||||||
|
*
|
||||||
|
* @author Adrian Humphreys
|
||||||
|
* @package environmentcheck
|
||||||
|
*/
|
||||||
|
class SessionCheck implements EnvironmentCheck
|
||||||
|
{
|
||||||
|
use Fetcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up check with URL
|
||||||
|
*
|
||||||
|
* @param string $url The route, excluding the domain
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function __construct($url = '')
|
||||||
|
{
|
||||||
|
$this->setURL($url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the response for URL does not create a session
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
$response = $this->client->get($this->getURL());
|
||||||
|
$cookie = $this->getCookie($response);
|
||||||
|
$fullURL = $this->getURL();
|
||||||
|
|
||||||
|
if ($cookie) {
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::ERROR,
|
||||||
|
"Sessions are being set for {$fullURL} : Set-Cookie => " . $cookie,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
EnvironmentCheck::OK,
|
||||||
|
"Sessions are not being created for {$fullURL} 👍",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get PHPSESSID or SECSESSID cookie set from the response if it exists.
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return string|null Cookie contents or null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public function getCookie(ResponseInterface $response)
|
||||||
|
{
|
||||||
|
$result = null;
|
||||||
|
$cookies = $response->getHeader('Set-Cookie');
|
||||||
|
|
||||||
|
foreach ($cookies as $cookie) {
|
||||||
|
if (strpos($cookie ?? '', 'SESSID') !== false) {
|
||||||
|
$result = $cookie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,11 @@
|
|||||||
namespace SilverStripe\EnvironmentCheck\Checks;
|
namespace SilverStripe\EnvironmentCheck\Checks;
|
||||||
|
|
||||||
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
use SilverStripe\FullTextSearch\Solr\Solr;
|
||||||
|
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the availability of all Solr indexes of given class.
|
* Check the availability of all Solr indexes
|
||||||
*
|
*
|
||||||
* If there are no indexes of given class found, the returned status will still be "OK".
|
* If there are no indexes of given class found, the returned status will still be "OK".
|
||||||
*
|
*
|
||||||
@ -13,19 +15,6 @@ use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
|||||||
*/
|
*/
|
||||||
class SolrIndexCheck implements EnvironmentCheck
|
class SolrIndexCheck implements EnvironmentCheck
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var null|string
|
|
||||||
*/
|
|
||||||
protected $indexClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $indexClass Limit the index checks to the specified class and all its subclasses.
|
|
||||||
*/
|
|
||||||
public function __construct($indexClass = null)
|
|
||||||
{
|
|
||||||
$this->indexClass = $indexClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -35,18 +24,16 @@ class SolrIndexCheck implements EnvironmentCheck
|
|||||||
{
|
{
|
||||||
$brokenCores = [];
|
$brokenCores = [];
|
||||||
|
|
||||||
/**
|
if (!class_exists(Solr::class)) {
|
||||||
* @todo Revisit this when silverstripe/fulltextsearch has 4.x compat
|
|
||||||
*/
|
|
||||||
if (!class_exists('\\Solr')) {
|
|
||||||
return [
|
return [
|
||||||
EnvironmentCheck::ERROR,
|
EnvironmentCheck::ERROR,
|
||||||
'Class `Solr` not found. Is the fulltextsearch module installed?'
|
'Class `' . Solr::class . '` not found. Is the fulltextsearch module installed?'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$service = \Solr::service();
|
$service = Solr::service();
|
||||||
foreach (\Solr::get_indexes($this->indexClass) as $index) {
|
foreach (Solr::get_indexes() as $index) {
|
||||||
|
/** @var SolrIndex $core */
|
||||||
$core = $index->getIndexName();
|
$core = $index->getIndexName();
|
||||||
if (!$service->coreIsActive($core)) {
|
if (!$service->coreIsActive($core)) {
|
||||||
$brokenCores[] = $core;
|
$brokenCores[] = $core;
|
||||||
@ -56,7 +43,7 @@ class SolrIndexCheck implements EnvironmentCheck
|
|||||||
if (!empty($brokenCores)) {
|
if (!empty($brokenCores)) {
|
||||||
return [
|
return [
|
||||||
EnvironmentCheck::ERROR,
|
EnvironmentCheck::ERROR,
|
||||||
'The following indexes are unavailable: ' . implode($brokenCores, ', ')
|
'The following indexes are unavailable: ' . implode(', ', $brokenCores)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class URLCheck implements EnvironmentCheck
|
|||||||
EnvironmentCheck::ERROR,
|
EnvironmentCheck::ERROR,
|
||||||
sprintf('Error retrieving "%s" (Code: %d)', $this->url, $response->getStatusCode())
|
sprintf('Error retrieving "%s" (Code: %d)', $this->url, $response->getStatusCode())
|
||||||
];
|
];
|
||||||
} elseif ($this->testString && (strpos($response->getBody(), $this->testString) === false)) {
|
} elseif ($this->testString && (strpos($response->getBody() ?? '', $this->testString ?? '') === false)) {
|
||||||
return [
|
return [
|
||||||
EnvironmentCheck::WARNING,
|
EnvironmentCheck::WARNING,
|
||||||
sprintf('Success retrieving "%s", but string "%s" not found', $this->url, $this->testString)
|
sprintf('Success retrieving "%s", but string "%s" not found', $this->url, $this->testString)
|
||||||
|
@ -43,7 +43,11 @@ class DevCheckController extends Controller
|
|||||||
$suite = $name;
|
$suite = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
$checker = new EnvironmentChecker($suite, 'Environment status');
|
/** @var EnvironmentChecker */
|
||||||
|
$checker = EnvironmentChecker::create($suite, 'Environment status')
|
||||||
|
->setRequest($request)
|
||||||
|
->setIncludeDetails(true);
|
||||||
|
|
||||||
$checker->init($this->config()->permission);
|
$checker->init($this->config()->permission);
|
||||||
|
|
||||||
return $checker;
|
return $checker;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace SilverStripe\EnvironmentCheck\Controllers;
|
namespace SilverStripe\EnvironmentCheck\Controllers;
|
||||||
|
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
|
use SilverStripe\Control\HTTPResponse_Exception;
|
||||||
use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +28,6 @@ class DevHealthController extends Controller
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// health check does not require permission to run
|
// health check does not require permission to run
|
||||||
|
|
||||||
$checker = new EnvironmentChecker('health', 'Site health');
|
$checker = new EnvironmentChecker('health', 'Site health');
|
||||||
$checker->setErrorCode(500);
|
$checker->setErrorCode(500);
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class EnvironmentCheckSuite
|
|||||||
/**
|
/**
|
||||||
* Run this test suite and return the result code of the worst result.
|
* Run this test suite and return the result code of the worst result.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return EnvironmentCheckSuiteResult
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
@ -125,7 +125,7 @@ class EnvironmentCheckSuite
|
|||||||
/**
|
/**
|
||||||
* Get instances of all the environment checks.
|
* Get instances of all the environment checks.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return EnvironmentChecker[]
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
protected function checkInstances()
|
protected function checkInstances()
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace SilverStripe\EnvironmentCheck;
|
namespace SilverStripe\EnvironmentCheck;
|
||||||
|
|
||||||
use Psr\Log\LogLevel;
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Control\Email\Email;
|
use SilverStripe\Control\Email\Email;
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
@ -12,7 +12,6 @@ use SilverStripe\Control\RequestHandler;
|
|||||||
use SilverStripe\Core\Environment;
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Dev\Deprecation;
|
use SilverStripe\Dev\Deprecation;
|
||||||
use SilverStripe\Security\BasicAuth;
|
|
||||||
use SilverStripe\Security\Member;
|
use SilverStripe\Security\Member;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
@ -41,6 +40,11 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
*/
|
*/
|
||||||
protected $title;
|
protected $title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $includeDetails = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
@ -104,42 +108,32 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
if (Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
if (Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
||||||
&& Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
&& Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
||||||
) {
|
) {
|
||||||
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
// Check that details are both provided, and match
|
||||||
// authenticate the input user/pass with the configured credentials
|
if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])
|
||||||
if (!(
|
|| $_SERVER['PHP_AUTH_USER'] != Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
||||||
$_SERVER['PHP_AUTH_USER'] == Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
|| $_SERVER['PHP_AUTH_PW'] != Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
||||||
&& $_SERVER['PHP_AUTH_PW'] == Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
|
// Fail check with basic auth challenge
|
||||||
$response = new HTTPResponse(null, 401);
|
$response = new HTTPResponse(null, 401);
|
||||||
$response->addHeader('WWW-Authenticate', "Basic realm=\"Environment check\"");
|
$response->addHeader('WWW-Authenticate', "Basic realm=\"Environment check\"");
|
||||||
// Exception is caught by RequestHandler->handleRequest() and will halt further execution
|
throw new HTTPResponse_Exception($response);
|
||||||
$e = new HTTPResponse_Exception(null, 401);
|
|
||||||
$e->setResponse($response);
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$response = new HTTPResponse(null, 401);
|
|
||||||
$response->addHeader('WWW-Authenticate', "Basic realm=\"Environment check\"");
|
|
||||||
// Exception is caught by RequestHandler->handleRequest() and will halt further execution
|
|
||||||
$e = new HTTPResponse_Exception(null, 401);
|
|
||||||
$e->setResponse($response);
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!$this->canAccess(null, $permission)) {
|
|
||||||
return $this->httpError(403);
|
|
||||||
}
|
}
|
||||||
|
} elseif (!$this->canAccess(null, $permission)) {
|
||||||
|
// Fail check with silverstripe login challenge
|
||||||
|
$result = Security::permissionFailure(
|
||||||
|
$this,
|
||||||
|
"You must have the {$permission} permission to access this check"
|
||||||
|
);
|
||||||
|
throw new HTTPResponse_Exception($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Determine if the current member can access the environment checker
|
||||||
|
*
|
||||||
* @param null|int|Member $member
|
* @param null|int|Member $member
|
||||||
* @param string $permission
|
* @param string $permission
|
||||||
*
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
|
||||||
* @throws HTTPResponse_Exception
|
|
||||||
*/
|
*/
|
||||||
public function canAccess($member = null, $permission = 'ADMIN')
|
public function canAccess($member = null, $permission = 'ADMIN')
|
||||||
{
|
{
|
||||||
@ -147,10 +141,6 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
$member = Security::getCurrentUser();
|
$member = Security::getCurrentUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$member) {
|
|
||||||
$member = BasicAuth::requireLogin($this->getRequest(), 'Environment Checker', $permission, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We allow access to this controller regardless of live-status or ADMIN permission only
|
// We allow access to this controller regardless of live-status or ADMIN permission only
|
||||||
// if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
|
// if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
|
||||||
if (Director::isDev()
|
if (Director::isDev()
|
||||||
@ -187,19 +177,31 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
$response->setStatusCode($this->errorCode);
|
$response->setStatusCode($this->errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
$resultText = $result->customise([
|
$data = [
|
||||||
'URL' => Director::absoluteBaseURL(),
|
'URL' => Director::absoluteBaseURL(),
|
||||||
'Title' => $this->title,
|
'Title' => $this->title,
|
||||||
'Name' => $this->checkSuiteName,
|
'Name' => $this->checkSuiteName,
|
||||||
'ErrorCode' => $this->errorCode,
|
'ErrorCode' => $this->errorCode
|
||||||
])->renderWith(__CLASS__);
|
];
|
||||||
|
|
||||||
|
$emailContent = $result->customise(array_merge($data, [
|
||||||
|
'IncludeDetails' => true
|
||||||
|
]))->renderWith(__CLASS__);
|
||||||
|
|
||||||
|
if (!$this->includeDetails) {
|
||||||
|
$webContent = $result->customise(array_merge($data, [
|
||||||
|
'IncludeDetails' => false
|
||||||
|
]))->renderWith(__CLASS__);
|
||||||
|
} else {
|
||||||
|
$webContent = $emailContent;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->config()->get('email_results') && !$result->ShouldPass()) {
|
if ($this->config()->get('email_results') && !$result->ShouldPass()) {
|
||||||
$email = new Email(
|
$email = new Email(
|
||||||
$this->config()->get('from_email_address'),
|
$this->config()->get('from_email_address'),
|
||||||
$this->config()->get('to_email_address'),
|
$this->config()->get('to_email_address'),
|
||||||
$this->title,
|
$this->title,
|
||||||
$resultText
|
$emailContent
|
||||||
);
|
);
|
||||||
$email->send();
|
$email->send();
|
||||||
}
|
}
|
||||||
@ -221,14 +223,14 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
|
|
||||||
// output the result as JSON if requested
|
// output the result as JSON if requested
|
||||||
if ($this->getRequest()->getExtension() == 'json'
|
if ($this->getRequest()->getExtension() == 'json'
|
||||||
|| strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false
|
|| strpos($this->getRequest()->getHeader('Accept') ?? '', 'application/json') !== false
|
||||||
) {
|
) {
|
||||||
$response->setBody($result->toJSON());
|
$response->setBody($result->toJSON());
|
||||||
$response->addHeader('Content-Type', 'application/json');
|
$response->addHeader('Content-Type', 'application/json');
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->setBody($resultText);
|
$response->setBody($webContent);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@ -244,73 +246,92 @@ class EnvironmentChecker extends RequestHandler
|
|||||||
Injector::inst()->get(LoggerInterface::class)->log($level, $message);
|
Injector::inst()->get(LoggerInterface::class)->log($level, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the HTTP status code that should be returned when there's an error.
|
* Set the HTTP status code that should be returned when there's an error.
|
||||||
*
|
*
|
||||||
* @param int $errorCode
|
* @param int $errorCode
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setErrorCode($errorCode)
|
public function setErrorCode($errorCode)
|
||||||
{
|
{
|
||||||
$this->errorCode = $errorCode;
|
$this->errorCode = $errorCode;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* Set whether to include the full breakdown of services
|
||||||
|
*
|
||||||
|
* @param bool $includeDetails
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setIncludeDetails($includeDetails)
|
||||||
|
{
|
||||||
|
$this->includeDetails = $includeDetails;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @param string $from
|
* @param string $from
|
||||||
*/
|
*/
|
||||||
public static function set_from_email_address($from)
|
public static function set_from_email_address($from)
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
static::config()->set('from_email_address', $from);
|
static::config()->set('from_email_address', $from);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
public static function get_from_email_address()
|
public static function get_from_email_address()
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
return static::config()->get('from_email_address');
|
return static::config()->get('from_email_address');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @param string $to
|
* @param string $to
|
||||||
*/
|
*/
|
||||||
public static function set_to_email_address($to)
|
public static function set_to_email_address($to)
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
static::config()->set('to_email_address', $to);
|
static::config()->set('to_email_address', $to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
public static function get_to_email_address()
|
public static function get_to_email_address()
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
return static::config()->get('to_email_address');
|
return static::config()->get('to_email_address');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @param bool $results
|
* @param bool $results
|
||||||
*/
|
*/
|
||||||
public static function set_email_results($results)
|
public static function set_email_results($results)
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
static::config()->set('email_results', $results);
|
static::config()->set('email_results', $results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated 2.0.0 Use config API instead
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function get_email_results()
|
public static function get_email_results()
|
||||||
{
|
{
|
||||||
Deprecation::notice('2.0', 'Use config API instead');
|
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||||
return static::config()->get('email_results');
|
return static::config()->get('email_results');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
49
src/Services/ClientFactory.php
Normal file
49
src/Services/ClientFactory.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Services;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client as GuzzleClient;
|
||||||
|
use SilverStripe\Core\Injector\Factory;
|
||||||
|
use SilverStripe\Core\Config\Configurable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class for creating HTTP client which are injected into some env check classes. Inject via YAML,
|
||||||
|
* arguments for Guzzle client can be supplied using "constructor" property or set as default_config.
|
||||||
|
*
|
||||||
|
* @see SilverStripe\EnvironmentCheck\Traits\Fetcher
|
||||||
|
*/
|
||||||
|
class ClientFactory implements Factory
|
||||||
|
{
|
||||||
|
use Configurable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default config for Guzzle client.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $default_config = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper to create a Guzzle client.
|
||||||
|
*
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function create($service, array $params = [])
|
||||||
|
{
|
||||||
|
return new GuzzleClient($this->getConfig($params));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge config provided from yaml with default config
|
||||||
|
*
|
||||||
|
* @param array $overrides
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConfig(array $overrides)
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
$this->config()->get('default_config'),
|
||||||
|
$overrides
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
51
src/Traits/Fetcher.php
Normal file
51
src/Traits/Fetcher.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Traits;
|
||||||
|
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple helper for env checks which require HTTP clients.
|
||||||
|
*
|
||||||
|
* @package environmentcheck
|
||||||
|
*/
|
||||||
|
trait Fetcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Client for making requests, set vi Injector.
|
||||||
|
*
|
||||||
|
* @see SilverStripe\EnvironmentCheck\Services
|
||||||
|
*
|
||||||
|
* @var GuzzleHttp\Client
|
||||||
|
*/
|
||||||
|
public $client = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute URL for requests.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set URL for requests.
|
||||||
|
*
|
||||||
|
* @param string $url Relative URL
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setURL($url)
|
||||||
|
{
|
||||||
|
$this->url = Director::absoluteURL($url);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for URL
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getURL()
|
||||||
|
{
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
}
|
@ -64,16 +64,18 @@
|
|||||||
<h1 class="$Status">$Title: $Status</h1>
|
<h1 class="$Status">$Title: $Status</h1>
|
||||||
<h2 class="website">Site: $URL</h2>
|
<h2 class="website">Site: $URL</h2>
|
||||||
|
|
||||||
|
<% if $IncludeDetails %>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Check</th> <th>Status</th> <th>Message</th></tr>
|
<tr><th>Check</th> <th>Status</th> <th>Message</th></tr>
|
||||||
<% loop $Details %>
|
<% loop $Details %>
|
||||||
<tr><td>$Check</td> <td class="$Status">$Status</td> <td>$Message.XML</td></tr>
|
<tr><td>$Check</td> <td class="$Status">$Status</td> <td>$Message.XML</td></tr>
|
||||||
<% end_loop %>
|
<% end_loop %>
|
||||||
</table>
|
</table>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
<% if $ShouldPass %>
|
<% if $ShouldPass %>
|
||||||
<p>Site is available</p>
|
<p>Site is available</p>
|
||||||
<p class="subtext">(you may check for the presence of the text 'Site is available' rather than an HTTP $ErrorCode error on this page, if you prefer.)</p>
|
<p class="subtext">(you may check for the presence of the text 'Site is available' rather than an HTTP $ErrorCode error on this page, if you prefer.<% if not $IncludeDetails %> Full details are available for logged in users at <a href="{$AbsoluteBaseURL}dev/check/">dev/check</a><% end_if %>)</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<% if $Name == "check" %>
|
<% if $Name == "check" %>
|
||||||
<p><b>A subsystem of the site is unavailable, but the site remains operational</b></p>
|
<p><b>A subsystem of the site is unavailable, but the site remains operational</b></p>
|
||||||
|
101
tests/Checks/CacheHeadersCheckTest.php
Normal file
101
tests/Checks/CacheHeadersCheckTest.php
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Tests\Checks;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
use SilverStripe\EnvironmentCheck\Checks\CacheHeadersCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test session checks.
|
||||||
|
*/
|
||||||
|
class CacheHeadersCheckTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test that directives that must be included, are.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testMustInclude()
|
||||||
|
{
|
||||||
|
// Create a mock and queue responses
|
||||||
|
$mock = new MockHandler([
|
||||||
|
new Response(200, ['Cache-Control' => 'must-revalidate', 'ETag' => '123']),
|
||||||
|
new Response(200, ['Cache-Control' =>'no-cache', 'ETag' => '123']),
|
||||||
|
new Response(200, ['ETag' => '123']),
|
||||||
|
new Response(200, ['Cache-Control' => 'must-revalidate, private', 'ETag' => '123']),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$handler = HandlerStack::create($mock);
|
||||||
|
$client = new Client(['handler' => $handler]);
|
||||||
|
|
||||||
|
$cacheHeadersCheck = new CacheHeadersCheck('/', ['must-revalidate']);
|
||||||
|
$cacheHeadersCheck->client = $client;
|
||||||
|
|
||||||
|
// Run checks for each response above
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that directives that must be excluded, are.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testMustExclude()
|
||||||
|
{
|
||||||
|
// Create a mock and queue responses
|
||||||
|
$mock = new MockHandler([
|
||||||
|
new Response(200, ['Cache-Control' => 'must-revalidate', 'ETag' => '123']),
|
||||||
|
new Response(200, ['Cache-Control' =>'no-cache', 'ETag' => '123']),
|
||||||
|
new Response(200, ['ETag' => '123']),
|
||||||
|
new Response(200, ['Cache-Control' =>'private, no-store', 'ETag' => '123']),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$handler = HandlerStack::create($mock);
|
||||||
|
$client = new Client(['handler' => $handler]);
|
||||||
|
|
||||||
|
$cacheHeadersCheck = new CacheHeadersCheck('/', [], ["no-store", "no-cache", "private"]);
|
||||||
|
$cacheHeadersCheck->client = $client;
|
||||||
|
|
||||||
|
// Run checks for each response above
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that Etag header must exist in response.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testEtag()
|
||||||
|
{
|
||||||
|
// Create a mock and queue responses
|
||||||
|
$mock = new MockHandler([
|
||||||
|
new Response(200, ['Cache-Control' => 'must-revalidate', 'ETag' => '123']),
|
||||||
|
new Response(200, ['Cache-Control' =>'no-cache']),
|
||||||
|
new Response(200, ['ETag' => '123']),
|
||||||
|
new Response(200, []),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$handler = HandlerStack::create($mock);
|
||||||
|
$client = new Client(['handler' => $handler]);
|
||||||
|
|
||||||
|
$cacheHeadersCheck = new CacheHeadersCheck('/');
|
||||||
|
$cacheHeadersCheck->client = $client;
|
||||||
|
|
||||||
|
// Run checks for each response above
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $cacheHeadersCheck->check());
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $cacheHeadersCheck->check());
|
||||||
|
}
|
||||||
|
}
|
@ -10,8 +10,6 @@ use SilverStripe\Security\Member;
|
|||||||
/**
|
/**
|
||||||
* Class DatabaseCheckTest
|
* Class DatabaseCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class DatabaseCheckTest extends SapphireTest
|
class DatabaseCheckTest extends SapphireTest
|
||||||
|
73
tests/Checks/EnvTypeCheckTest.php
Normal file
73
tests/Checks/EnvTypeCheckTest.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Tests\Checks;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Kernel;
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
use SilverStripe\EnvironmentCheck\Checks\EnvTypeCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the env setting check.
|
||||||
|
*/
|
||||||
|
class EnvTypeCheckTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check is OK when in live mode
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testEnvSettingLive()
|
||||||
|
{
|
||||||
|
/** @var Kernel $kernel */
|
||||||
|
$kernel = Injector::inst()->get(Kernel::class);
|
||||||
|
$kernel->setEnvironment('live');
|
||||||
|
|
||||||
|
$this->assertTrue(Director::isLive());
|
||||||
|
|
||||||
|
$checker = Injector::inst()->get(EnvTypeCheck::class);
|
||||||
|
$result = $checker->check();
|
||||||
|
|
||||||
|
$this->assertSame($result[0], EnvironmentCheck::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check is ERROR when in test mode
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testEnvSettingTest()
|
||||||
|
{
|
||||||
|
/** @var Kernel $kernel */
|
||||||
|
$kernel = Injector::inst()->get(Kernel::class);
|
||||||
|
$kernel->setEnvironment('test');
|
||||||
|
|
||||||
|
$this->assertTrue(Director::isTest());
|
||||||
|
|
||||||
|
$checker = Injector::inst()->get(EnvTypeCheck::class);
|
||||||
|
$result = $checker->check();
|
||||||
|
|
||||||
|
$this->assertSame($result[0], EnvironmentCheck::ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check is ERROR when in dev mode
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testEnvSettingDev()
|
||||||
|
{
|
||||||
|
/** @var Kernel $kernel */
|
||||||
|
$kernel = Injector::inst()->get(Kernel::class);
|
||||||
|
$kernel->setEnvironment('dev');
|
||||||
|
|
||||||
|
$this->assertTrue(Director::isDev());
|
||||||
|
|
||||||
|
$checker = Injector::inst()->get(EnvTypeCheck::class);
|
||||||
|
$result = $checker->check();
|
||||||
|
|
||||||
|
$this->assertSame($result[0], EnvironmentCheck::ERROR);
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,6 @@ use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
|||||||
/**
|
/**
|
||||||
* Class ExternalURLCheckTest
|
* Class ExternalURLCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class ExternalURLCheckTest extends SapphireTest
|
class ExternalURLCheckTest extends SapphireTest
|
||||||
|
@ -9,8 +9,6 @@ use SilverStripe\Dev\SapphireTest;
|
|||||||
/**
|
/**
|
||||||
* Class FileWritableCheckTest
|
* Class FileWritableCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class FileWritableCheckTest extends SapphireTest
|
class FileWritableCheckTest extends SapphireTest
|
||||||
|
@ -9,8 +9,6 @@ use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
|||||||
/**
|
/**
|
||||||
* Class HasClassCheckTest
|
* Class HasClassCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class HasClassCheckTest extends SapphireTest
|
class HasClassCheckTest extends SapphireTest
|
||||||
|
@ -9,8 +9,6 @@ use SilverStripe\Dev\SapphireTest;
|
|||||||
/**
|
/**
|
||||||
* Class HasFunctionCheckTest
|
* Class HasFunctionCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class HasFunctionCheckTest extends SapphireTest
|
class HasFunctionCheckTest extends SapphireTest
|
||||||
|
76
tests/Checks/SessionCheckTest.php
Normal file
76
tests/Checks/SessionCheckTest.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\EnvironmentCheck\Tests\Checks;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
|
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||||
|
use SilverStripe\EnvironmentCheck\Checks\SessionCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test session checks.
|
||||||
|
*/
|
||||||
|
class SessionCheckTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var SilverStripe\EnvironmentCheck\Checks\SessionCheck
|
||||||
|
*/
|
||||||
|
public $sessionCheck = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a session check for use by tests.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->sessionCheck = new SessionCheck('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Env check reports error when session cookies are being set.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testSessionSet()
|
||||||
|
{
|
||||||
|
// Create a mock and queue two responses.
|
||||||
|
$mock = new MockHandler([
|
||||||
|
new Response(200, ['Set-Cookie' => 'PHPSESSID:foo']),
|
||||||
|
new Response(200, ['Set-Cookie' => 'SECSESSID:bar'])
|
||||||
|
]);
|
||||||
|
|
||||||
|
$handler = HandlerStack::create($mock);
|
||||||
|
$client = new Client(['handler' => $handler]);
|
||||||
|
$this->sessionCheck->client = $client;
|
||||||
|
|
||||||
|
// Check for PHPSESSID
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $this->sessionCheck->check());
|
||||||
|
|
||||||
|
// Check for SECSESSID
|
||||||
|
$this->assertContains(EnvironmentCheck::ERROR, $this->sessionCheck->check());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Env check responds OK when no session cookies are set in response.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testSessionNotSet()
|
||||||
|
{
|
||||||
|
// Create a mock and queue two responses.
|
||||||
|
$mock = new MockHandler([
|
||||||
|
new Response(200)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$handler = HandlerStack::create($mock);
|
||||||
|
$client = new Client(['handler' => $handler]);
|
||||||
|
$this->sessionCheck->client = $client;
|
||||||
|
|
||||||
|
$this->assertContains(EnvironmentCheck::OK, $this->sessionCheck->check());
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,6 @@ use SilverStripe\Dev\SapphireTest;
|
|||||||
/**
|
/**
|
||||||
* Class URLCheckTest
|
* Class URLCheckTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class URLCheckTest extends SapphireTest
|
class URLCheckTest extends SapphireTest
|
||||||
|
@ -10,8 +10,6 @@ use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
|||||||
/**
|
/**
|
||||||
* Class DevCheckControllerTest
|
* Class DevCheckControllerTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class DevCheckControllerTest extends SapphireTest
|
class DevCheckControllerTest extends SapphireTest
|
||||||
@ -30,4 +28,14 @@ class DevCheckControllerTest extends SapphireTest
|
|||||||
|
|
||||||
$this->assertInstanceOf(EnvironmentChecker::class, $controller->index($request));
|
$this->assertInstanceOf(EnvironmentChecker::class, $controller->index($request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCheckIncludesDetails()
|
||||||
|
{
|
||||||
|
$controller = new DevCheckController();
|
||||||
|
$request = new HTTPRequest('GET', 'example.com');
|
||||||
|
|
||||||
|
$response = $controller->index($request)->index();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('<table>', $response->getBody());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,6 @@ use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
|||||||
/**
|
/**
|
||||||
* Class DevHealthControllerTest
|
* Class DevHealthControllerTest
|
||||||
*
|
*
|
||||||
* @mixin PHPUnit_Framework_TestCase
|
|
||||||
*
|
|
||||||
* @package environmentcheck
|
* @package environmentcheck
|
||||||
*/
|
*/
|
||||||
class DevHealthControllerTest extends SapphireTest
|
class DevHealthControllerTest extends SapphireTest
|
||||||
@ -39,4 +37,15 @@ class DevHealthControllerTest extends SapphireTest
|
|||||||
|
|
||||||
$this->assertInstanceOf(EnvironmentChecker::class, $controller->index($request));
|
$this->assertInstanceOf(EnvironmentChecker::class, $controller->index($request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testHealthDoesNotIncludeDetails()
|
||||||
|
{
|
||||||
|
$controller = new DevHealthController();
|
||||||
|
$request = new HTTPRequest('GET', 'example.com');
|
||||||
|
|
||||||
|
$response = $controller->index($request)->index();
|
||||||
|
|
||||||
|
$this->assertFalse(strpos($response->getBody(), '<table>'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class EnvironmentCheckerTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
protected $usesDatabase = true;
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
protected function tearDown()
|
protected function tearDown(): void
|
||||||
{
|
{
|
||||||
EnvironmentCheckSuite::reset();
|
EnvironmentCheckSuite::reset();
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
@ -61,8 +61,8 @@ class EnvironmentCheckerTest extends SapphireTest
|
|||||||
$logger->expects($this->once())
|
$logger->expects($this->once())
|
||||||
->method('log')
|
->method('log')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
$this->equalTo(LogLevel::WARNING),
|
[$this->equalTo(LogLevel::WARNING)],
|
||||||
$this->anything()
|
[$this->anything()]
|
||||||
);
|
);
|
||||||
|
|
||||||
Injector::inst()->registerService($logger, LoggerInterface::class);
|
Injector::inst()->registerService($logger, LoggerInterface::class);
|
||||||
|
Loading…
Reference in New Issue
Block a user