mirror of
https://github.com/silverstripe/silverstripe-environmentcheck
synced 2024-09-30 05:09:05 +02:00
Compare commits
No commits in common. "2" and "2.0.0-beta1" have entirely different histories.
2
...
2.0.0-beta
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@ -1,11 +0,0 @@
|
||||
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
16
.github/workflows/dispatch-ci.yml
vendored
@ -1,16 +0,0 @@
|
||||
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
17
.github/workflows/keepalive.yml
vendored
@ -1,17 +0,0 @@
|
||||
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
|
9
.scrutinizer.yml
Normal file
9
.scrutinizer.yml
Normal file
@ -0,0 +1,9 @@
|
||||
inherit: true
|
||||
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
duplication: true
|
||||
|
||||
filter:
|
||||
paths: [src/*, tests/*]
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
@ -0,0 +1,33 @@
|
||||
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
|
@ -2,12 +2,8 @@
|
||||
Name: environmentcheckinjector
|
||||
---
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
CacheHeadersCheck:
|
||||
class: SilverStripe\EnvironmentCheck\Checks\CacheHeadersCheck
|
||||
DatabaseCheck:
|
||||
class: SilverStripe\EnvironmentCheck\Checks\DatabaseCheck
|
||||
EnvTypeCheck:
|
||||
class: SilverStripe\EnvironmentCheck\Checks\EnvTypeCheck
|
||||
ExternalURLCheck:
|
||||
class: SilverStripe\EnvironmentCheck\Checks\ExternalURLCheck
|
||||
FileAccessibilityAndValidationCheck:
|
||||
@ -26,14 +22,3 @@ SilverStripe\Core\Injector\Injector:
|
||||
class: SilverStripe\EnvironmentCheck\Checks\SolrIndexCheck
|
||||
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,14 +12,3 @@ SilverStripe\Dev\DevelopmentAdmin:
|
||||
controller: Silverstripe\EnvironmentCheck\Controllers\DevCheckController
|
||||
links:
|
||||
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,17 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [2.1.0]
|
||||
|
||||
* Add new checks:
|
||||
* Environment type
|
||||
* Session
|
||||
* Cache Headers
|
||||
* Fix basic auth
|
||||
* Add unit tests
|
||||
* PSR-2 Conformance
|
||||
|
||||
## [2.0.0]
|
||||
## [2.0.0] - unreleased
|
||||
|
||||
* Minimum versions required:
|
||||
* SilverStripe 4.x
|
||||
|
@ -3,12 +3,7 @@
|
||||
"description": "Provides an API for building environment tests",
|
||||
"license": "BSD-3-Clause",
|
||||
"type": "silverstripe-vendormodule",
|
||||
"keywords": [
|
||||
"silverstripe",
|
||||
"testing",
|
||||
"environment",
|
||||
"check"
|
||||
],
|
||||
"keywords": ["silverstripe", "testing", "environment", "check"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Will Rossiter",
|
||||
@ -20,16 +15,18 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"silverstripe/framework": "^4.10",
|
||||
"silverstripe/versioned": "^1.0",
|
||||
"guzzlehttp/guzzle": "^6.3.3 || ^7"
|
||||
"silverstripe/framework": "^4.0",
|
||||
"silverstripe/versioned": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"squizlabs/php_codesniffer": "^3.0"
|
||||
},
|
||||
"extra": [],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SilverStripe\\EnvironmentCheck\\": "src/",
|
||||
|
@ -2,9 +2,6 @@
|
||||
<ruleset name="SilverStripe">
|
||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
|
||||
<rule ref="PSR2" >
|
||||
<!-- Current exclusions -->
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||
|
@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Default">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<testsuite name="Default">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
|
||||
<filter>
|
||||
<whitelist addUncoveredFilesFromWhitelist="true">
|
||||
|
@ -1,7 +1,10 @@
|
||||
# Silverstripe Environment Checker Module
|
||||
# SilverStripe Environment Checker Module
|
||||
|
||||
[![CI](https://github.com/silverstripe/silverstripe-environmentcheck/actions/workflows/ci.yml/badge.svg)](https://github.com/silverstripe/silverstripe-environmentcheck/actions/workflows/ci.yml)
|
||||
[![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
|
||||
[![Build Status](https://travis-ci.org/silverstripe/silverstripe-environmentcheck.svg?branch=master)](https://travis-ci.org/silverstripe/silverstripe-environmentcheck)
|
||||
[![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)
|
||||
[![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.
|
||||
|
||||
@ -11,10 +14,10 @@ This module adds an API for running environment checks to your API.
|
||||
|
||||
## Requirements
|
||||
|
||||
* Silverstripe 4.x
|
||||
* PHP 7.3
|
||||
* SilverStripe 4.x
|
||||
* PHP 5.6+
|
||||
|
||||
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?
|
||||
|
||||
@ -82,17 +85,12 @@ SilverStripe\EnvironmentCheck\EnvironmentCheckSuite:
|
||||
* `HasClassCheck`: Check that the given class exists.
|
||||
This can be used to check that PHP modules or features are installed.
|
||||
* `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.
|
||||
Useful for files which should be frequently auto-generated,
|
||||
like static caches, as well as for backup files and folders.
|
||||
* `ExternalURLCheck`: Checks that one or more URLs are reachable via HTTP.
|
||||
* `SMTPConnectCheck`: Checks if the SMTP connection configured through PHP.ini works as expected.
|
||||
* `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
|
||||
|
||||
@ -108,7 +106,7 @@ SilverStripe\EnvironmentCheck\EnvironmentChecker:
|
||||
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
|
||||
result of `EnvironmentCheck->check()`.
|
||||
|
@ -1,207 +0,0 @@
|
||||
<?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}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?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)
|
||||
{
|
||||
if ($urls) {
|
||||
$this->urls = explode(' ', $urls ?? '');
|
||||
$this->urls = explode(' ', $urls);
|
||||
}
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
@ -55,7 +55,7 @@ class ExternalURLCheck implements EnvironmentCheck
|
||||
foreach ($urls as $url) {
|
||||
$ch = curl_init();
|
||||
$chs[] = $ch;
|
||||
curl_setopt_array($ch, $this->getCurlOpts($url) ?? []);
|
||||
curl_setopt_array($ch, $this->getCurlOpts($url));
|
||||
}
|
||||
// Parallel execution for faster performance
|
||||
$mh = curl_multi_init();
|
||||
|
@ -96,7 +96,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
||||
$files = $this->getFiles();
|
||||
if ($files) {
|
||||
$fileTypeValidateFunc = $this->fileTypeValidateFunc;
|
||||
if (method_exists($this, $fileTypeValidateFunc ?? '')) {
|
||||
if (method_exists($this, $fileTypeValidateFunc)) {
|
||||
$invalidFiles = [];
|
||||
$validFiles = [];
|
||||
|
||||
@ -109,7 +109,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
||||
}
|
||||
|
||||
// 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;
|
||||
foreach ($validFiles as $vf) {
|
||||
$validFileList .= $vf . PHP_EOL;
|
||||
@ -130,7 +130,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
||||
];
|
||||
}
|
||||
} else {
|
||||
if (count($invalidFiles ?? []) == 0) {
|
||||
if (count($invalidFiles) == 0) {
|
||||
$checkReturn = [EnvironmentCheck::OK, 'All files valideted'];
|
||||
} else {
|
||||
$invalidFileList = PHP_EOL;
|
||||
@ -180,7 +180,7 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
||||
*/
|
||||
private function jsonValidate($file)
|
||||
{
|
||||
$json = json_decode(file_get_contents($file ?? '') ?? '');
|
||||
$json = json_decode(file_get_contents($file));
|
||||
if (!$json) {
|
||||
return false;
|
||||
}
|
||||
@ -204,6 +204,6 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck
|
||||
*/
|
||||
protected function getFiles()
|
||||
{
|
||||
return glob($this->path ?? '');
|
||||
return glob($this->path);
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class FileAgeCheck implements EnvironmentCheck
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$cutoffTime = strtotime($this->relativeAge ?? '', DBDatetime::now()->Format('U'));
|
||||
$cutoffTime = strtotime($this->relativeAge, DBDatetime::now()->Format('U'));
|
||||
$files = $this->getFiles();
|
||||
$invalidFiles = [];
|
||||
$validFiles = [];
|
||||
@ -127,10 +127,10 @@ class FileAgeCheck implements EnvironmentCheck
|
||||
}
|
||||
|
||||
// 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, ''];
|
||||
}
|
||||
if (count($invalidFiles ?? []) == 0) {
|
||||
if (count($invalidFiles) == 0) {
|
||||
return [EnvironmentCheck::OK, ''];
|
||||
}
|
||||
return [
|
||||
@ -146,6 +146,6 @@ class FileAgeCheck implements EnvironmentCheck
|
||||
*/
|
||||
protected function getFiles()
|
||||
{
|
||||
return glob($this->path ?? '');
|
||||
return glob($this->path);
|
||||
}
|
||||
}
|
||||
|
@ -34,22 +34,22 @@ class FileWriteableCheck implements EnvironmentCheck
|
||||
if ($this->path[0] == '/') {
|
||||
$filename = $this->path;
|
||||
} 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 ?? '')) {
|
||||
$isWriteable = is_writeable($filename ?? '');
|
||||
if (file_exists($filename)) {
|
||||
$isWriteable = is_writeable($filename);
|
||||
} else {
|
||||
$isWriteable = is_writeable(dirname($filename ?? ''));
|
||||
$isWriteable = is_writeable(dirname($filename));
|
||||
}
|
||||
|
||||
if (!$isWriteable) {
|
||||
if (function_exists('posix_getgroups')) {
|
||||
$userID = posix_geteuid();
|
||||
$user = posix_getpwuid($userID ?? 0);
|
||||
$user = posix_getpwuid($userID);
|
||||
|
||||
$currentOwnerID = fileowner(file_exists($filename ?? '') ? $filename : dirname($filename ?? ''));
|
||||
$currentOwner = posix_getpwuid($currentOwnerID ?? 0);
|
||||
$currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename));
|
||||
$currentOwner = posix_getpwuid($currentOwnerID);
|
||||
|
||||
$message = "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe file is "
|
||||
. "currently owned by '$currentOwner[name]'. ";
|
||||
@ -60,8 +60,8 @@ class FileWriteableCheck implements EnvironmentCheck
|
||||
$groups = posix_getgroups();
|
||||
$groupList = [];
|
||||
foreach ($groups as $group) {
|
||||
$groupInfo = posix_getgrgid($group ?? 0);
|
||||
if (in_array($currentOwner['name'], $groupInfo['members'] ?? [])) {
|
||||
$groupInfo = posix_getgrgid($group);
|
||||
if (in_array($currentOwner['name'], $groupInfo['members'])) {
|
||||
$groupList[] = $groupInfo['name'];
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class HasClassCheck implements EnvironmentCheck
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
if (class_exists($this->className ?? '')) {
|
||||
if (class_exists($this->className)) {
|
||||
return [EnvironmentCheck::OK, 'Class ' . $this->className.' exists'];
|
||||
}
|
||||
return [EnvironmentCheck::ERROR, 'Class ' . $this->className.' doesn\'t exist'];
|
||||
|
@ -31,7 +31,7 @@ class HasFunctionCheck implements EnvironmentCheck
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
if (function_exists($this->functionName ?? '')) {
|
||||
if (function_exists($this->functionName)) {
|
||||
return [EnvironmentCheck::OK, $this->functionName . '() exists'];
|
||||
}
|
||||
return [EnvironmentCheck::ERROR, $this->functionName . '() doesn\'t exist'];
|
||||
|
@ -57,7 +57,7 @@ class SMTPConnectCheck implements EnvironmentCheck
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$f = @fsockopen($this->host ?? '', $this->port ?? 0, $errno, $errstr, $this->timeout);
|
||||
$f = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
|
||||
if (!$f) {
|
||||
return [
|
||||
EnvironmentCheck::ERROR,
|
||||
@ -67,7 +67,7 @@ class SMTPConnectCheck implements EnvironmentCheck
|
||||
|
||||
fwrite($f, "HELO its_me\r\n");
|
||||
$response = fread($f, 26);
|
||||
if (substr($response ?? '', 0, 3) != '220') {
|
||||
if (substr($response, 0, 3) != '220') {
|
||||
return [
|
||||
EnvironmentCheck::ERROR,
|
||||
sprintf('Invalid mail server response: %s', $response)
|
||||
|
@ -1,71 +0,0 @@
|
||||
<?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,11 +3,9 @@
|
||||
namespace SilverStripe\EnvironmentCheck\Checks;
|
||||
|
||||
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||
use SilverStripe\FullTextSearch\Solr\Solr;
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
|
||||
/**
|
||||
* Check the availability of all Solr indexes
|
||||
* Check the availability of all Solr indexes of given class.
|
||||
*
|
||||
* If there are no indexes of given class found, the returned status will still be "OK".
|
||||
*
|
||||
@ -15,6 +13,19 @@ use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
*/
|
||||
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}
|
||||
*
|
||||
@ -24,16 +35,18 @@ class SolrIndexCheck implements EnvironmentCheck
|
||||
{
|
||||
$brokenCores = [];
|
||||
|
||||
if (!class_exists(Solr::class)) {
|
||||
/**
|
||||
* @todo Revisit this when silverstripe/fulltextsearch has 4.x compat
|
||||
*/
|
||||
if (!class_exists('\\Solr')) {
|
||||
return [
|
||||
EnvironmentCheck::ERROR,
|
||||
'Class `' . Solr::class . '` not found. Is the fulltextsearch module installed?'
|
||||
'Class `Solr` not found. Is the fulltextsearch module installed?'
|
||||
];
|
||||
}
|
||||
|
||||
$service = Solr::service();
|
||||
foreach (Solr::get_indexes() as $index) {
|
||||
/** @var SolrIndex $core */
|
||||
$service = \Solr::service();
|
||||
foreach (\Solr::get_indexes($this->indexClass) as $index) {
|
||||
$core = $index->getIndexName();
|
||||
if (!$service->coreIsActive($core)) {
|
||||
$brokenCores[] = $core;
|
||||
@ -43,7 +56,7 @@ class SolrIndexCheck implements EnvironmentCheck
|
||||
if (!empty($brokenCores)) {
|
||||
return [
|
||||
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,
|
||||
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 [
|
||||
EnvironmentCheck::WARNING,
|
||||
sprintf('Success retrieving "%s", but string "%s" not found', $this->url, $this->testString)
|
||||
|
@ -43,11 +43,7 @@ class DevCheckController extends Controller
|
||||
$suite = $name;
|
||||
}
|
||||
|
||||
/** @var EnvironmentChecker */
|
||||
$checker = EnvironmentChecker::create($suite, 'Environment status')
|
||||
->setRequest($request)
|
||||
->setIncludeDetails(true);
|
||||
|
||||
$checker = new EnvironmentChecker($suite, 'Environment status');
|
||||
$checker->init($this->config()->permission);
|
||||
|
||||
return $checker;
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace SilverStripe\EnvironmentCheck\Controllers;
|
||||
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\HTTPResponse_Exception;
|
||||
use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
||||
|
||||
/**
|
||||
@ -28,6 +27,7 @@ class DevHealthController extends Controller
|
||||
public function index()
|
||||
{
|
||||
// health check does not require permission to run
|
||||
|
||||
$checker = new EnvironmentChecker('health', 'Site health');
|
||||
$checker->setErrorCode(500);
|
||||
|
||||
|
@ -101,7 +101,7 @@ class EnvironmentCheckSuite
|
||||
/**
|
||||
* Run this test suite and return the result code of the worst result.
|
||||
*
|
||||
* @return EnvironmentCheckSuiteResult
|
||||
* @return int
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
@ -125,7 +125,7 @@ class EnvironmentCheckSuite
|
||||
/**
|
||||
* Get instances of all the environment checks.
|
||||
*
|
||||
* @return EnvironmentChecker[]
|
||||
* @return array
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function checkInstances()
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace SilverStripe\EnvironmentCheck;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\Email\Email;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
@ -12,6 +12,7 @@ use SilverStripe\Control\RequestHandler;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Security\BasicAuth;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\Security\Security;
|
||||
@ -40,11 +41,6 @@ class EnvironmentChecker extends RequestHandler
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $includeDetails = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
@ -108,32 +104,42 @@ class EnvironmentChecker extends RequestHandler
|
||||
if (Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
||||
&& Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
||||
) {
|
||||
// Check that details are both provided, and match
|
||||
if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])
|
||||
|| $_SERVER['PHP_AUTH_USER'] != Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
||||
|| $_SERVER['PHP_AUTH_PW'] != Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
||||
) {
|
||||
// Fail check with basic auth challenge
|
||||
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
||||
// authenticate the input user/pass with the configured credentials
|
||||
if (!(
|
||||
$_SERVER['PHP_AUTH_USER'] == Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
|
||||
&& $_SERVER['PHP_AUTH_PW'] == Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
|
||||
)
|
||||
) {
|
||||
$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 {
|
||||
$response = new HTTPResponse(null, 401);
|
||||
$response->addHeader('WWW-Authenticate', "Basic realm=\"Environment check\"");
|
||||
throw new HTTPResponse_Exception($response);
|
||||
// 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 string $permission
|
||||
* @param string $permission
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws HTTPResponse_Exception
|
||||
*/
|
||||
public function canAccess($member = null, $permission = 'ADMIN')
|
||||
{
|
||||
@ -141,6 +147,10 @@ class EnvironmentChecker extends RequestHandler
|
||||
$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
|
||||
// if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
|
||||
if (Director::isDev()
|
||||
@ -177,31 +187,19 @@ class EnvironmentChecker extends RequestHandler
|
||||
$response->setStatusCode($this->errorCode);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'URL' => Director::absoluteBaseURL(),
|
||||
'Title' => $this->title,
|
||||
'Name' => $this->checkSuiteName,
|
||||
'ErrorCode' => $this->errorCode
|
||||
];
|
||||
|
||||
$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;
|
||||
}
|
||||
$resultText = $result->customise([
|
||||
'URL' => Director::absoluteBaseURL(),
|
||||
'Title' => $this->title,
|
||||
'Name' => $this->checkSuiteName,
|
||||
'ErrorCode' => $this->errorCode,
|
||||
])->renderWith(__CLASS__);
|
||||
|
||||
if ($this->config()->get('email_results') && !$result->ShouldPass()) {
|
||||
$email = new Email(
|
||||
$this->config()->get('from_email_address'),
|
||||
$this->config()->get('to_email_address'),
|
||||
$this->title,
|
||||
$emailContent
|
||||
$resultText
|
||||
);
|
||||
$email->send();
|
||||
}
|
||||
@ -223,14 +221,14 @@ class EnvironmentChecker extends RequestHandler
|
||||
|
||||
// output the result as JSON if requested
|
||||
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->addHeader('Content-Type', 'application/json');
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response->setBody($webContent);
|
||||
$response->setBody($resultText);
|
||||
|
||||
return $response;
|
||||
}
|
||||
@ -239,99 +237,80 @@ class EnvironmentChecker extends RequestHandler
|
||||
* Sends a log entry to the configured PSR-3 LoggerInterface
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $level
|
||||
* @param int $level
|
||||
*/
|
||||
public function log($message, $level)
|
||||
{
|
||||
Injector::inst()->get(LoggerInterface::class)->log($level, $message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the HTTP status code that should be returned when there's an error.
|
||||
*
|
||||
* @param int $errorCode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setErrorCode($errorCode)
|
||||
{
|
||||
$this->errorCode = $errorCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @deprecated
|
||||
* @param string $from
|
||||
*/
|
||||
public static function set_from_email_address($from)
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
static::config()->set('from_email_address', $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Use config API instead
|
||||
* @deprecated
|
||||
* @return null|string
|
||||
*/
|
||||
public static function get_from_email_address()
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
return static::config()->get('from_email_address');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Use config API instead
|
||||
* @deprecated
|
||||
* @param string $to
|
||||
*/
|
||||
public static function set_to_email_address($to)
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
static::config()->set('to_email_address', $to);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Use config API instead
|
||||
* @deprecated
|
||||
* @return null|string
|
||||
*/
|
||||
public static function get_to_email_address()
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
return static::config()->get('to_email_address');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Use config API instead
|
||||
* @deprecated
|
||||
* @param bool $results
|
||||
*/
|
||||
public static function set_email_results($results)
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
static::config()->set('email_results', $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.0.0 Use config API instead
|
||||
* @deprecated
|
||||
* @return bool
|
||||
*/
|
||||
public static function get_email_results()
|
||||
{
|
||||
Deprecation::notice('2.0.0', 'Use config API instead');
|
||||
Deprecation::notice('2.0', 'Use config API instead');
|
||||
return static::config()->get('email_results');
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?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
|
||||
);
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
<?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,18 +64,16 @@
|
||||
<h1 class="$Status">$Title: $Status</h1>
|
||||
<h2 class="website">Site: $URL</h2>
|
||||
|
||||
<% if $IncludeDetails %>
|
||||
<table>
|
||||
<tr><th>Check</th> <th>Status</th> <th>Message</th></tr>
|
||||
<% loop $Details %>
|
||||
<tr><td>$Check</td> <td class="$Status">$Status</td> <td>$Message.XML</td></tr>
|
||||
<% end_loop %>
|
||||
</table>
|
||||
<% end_if %>
|
||||
|
||||
<% if $ShouldPass %>
|
||||
<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.<% if not $IncludeDetails %> Full details are available for logged in users at <a href="{$AbsoluteBaseURL}dev/check/">dev/check</a><% end_if %>)</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>
|
||||
<% else %>
|
||||
<% if $Name == "check" %>
|
||||
<p><b>A subsystem of the site is unavailable, but the site remains operational</b></p>
|
||||
|
@ -1,101 +0,0 @@
|
||||
<?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,6 +10,8 @@ use SilverStripe\Security\Member;
|
||||
/**
|
||||
* Class DatabaseCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class DatabaseCheckTest extends SapphireTest
|
||||
|
@ -1,73 +0,0 @@
|
||||
<?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,6 +9,8 @@ use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||
/**
|
||||
* Class ExternalURLCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class ExternalURLCheckTest extends SapphireTest
|
||||
|
@ -9,6 +9,8 @@ use SilverStripe\Dev\SapphireTest;
|
||||
/**
|
||||
* Class FileWritableCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class FileWritableCheckTest extends SapphireTest
|
||||
|
@ -9,6 +9,8 @@ use SilverStripe\EnvironmentCheck\EnvironmentCheck;
|
||||
/**
|
||||
* Class HasClassCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class HasClassCheckTest extends SapphireTest
|
||||
|
@ -9,6 +9,8 @@ use SilverStripe\Dev\SapphireTest;
|
||||
/**
|
||||
* Class HasFunctionCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class HasFunctionCheckTest extends SapphireTest
|
||||
|
@ -1,76 +0,0 @@
|
||||
<?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,6 +9,8 @@ use SilverStripe\Dev\SapphireTest;
|
||||
/**
|
||||
* Class URLCheckTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class URLCheckTest extends SapphireTest
|
||||
|
@ -10,6 +10,8 @@ use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
||||
/**
|
||||
* Class DevCheckControllerTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class DevCheckControllerTest extends SapphireTest
|
||||
@ -28,14 +30,4 @@ class DevCheckControllerTest extends SapphireTest
|
||||
|
||||
$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,6 +10,8 @@ use SilverStripe\EnvironmentCheck\EnvironmentChecker;
|
||||
/**
|
||||
* Class DevHealthControllerTest
|
||||
*
|
||||
* @mixin PHPUnit_Framework_TestCase
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class DevHealthControllerTest extends SapphireTest
|
||||
@ -37,15 +39,4 @@ class DevHealthControllerTest extends SapphireTest
|
||||
|
||||
$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 function tearDown(): void
|
||||
protected function tearDown()
|
||||
{
|
||||
EnvironmentCheckSuite::reset();
|
||||
parent::tearDown();
|
||||
@ -61,8 +61,8 @@ class EnvironmentCheckerTest extends SapphireTest
|
||||
$logger->expects($this->once())
|
||||
->method('log')
|
||||
->withConsecutive(
|
||||
[$this->equalTo(LogLevel::WARNING)],
|
||||
[$this->anything()]
|
||||
$this->equalTo(LogLevel::WARNING),
|
||||
$this->anything()
|
||||
);
|
||||
|
||||
Injector::inst()->registerService($logger, LoggerInterface::class);
|
||||
|
Loading…
Reference in New Issue
Block a user