diff --git a/.gitignore b/.gitignore index e6c3baaf..2f7ff706 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ composer.lock *.log www/manual/* !www/manual/index.php +config/php/fpm/standardebooks.org-secrets.ini diff --git a/config/php/fpm/standardebooks.org.ini b/config/php/fpm/standardebooks.org.ini index 0e0de0e3..7083df9a 100644 --- a/config/php/fpm/standardebooks.org.ini +++ b/config/php/fpm/standardebooks.org.ini @@ -9,10 +9,12 @@ max_execution_time = 120 allow_url_fopen = false allow_url_include = false expose_php = off -site_status = "live" [Date] date.timezone = Etc/UTC [opcache] opcache.validate_timestamps = off + +[se] +se.site_status = "live" diff --git a/config/php/fpm/standardebooks.test.ini b/config/php/fpm/standardebooks.test.ini index 0e0de0e3..58397878 100644 --- a/config/php/fpm/standardebooks.test.ini +++ b/config/php/fpm/standardebooks.test.ini @@ -9,10 +9,12 @@ max_execution_time = 120 allow_url_fopen = false allow_url_include = false expose_php = off -site_status = "live" [Date] date.timezone = Etc/UTC [opcache] opcache.validate_timestamps = off + +[se] +se.site_status = "dev" diff --git a/config/phpstan/phpstan.neon b/config/phpstan/phpstan.neon index 73328637..c5b5d7c1 100644 --- a/config/phpstan/phpstan.neon +++ b/config/phpstan/phpstan.neon @@ -16,9 +16,6 @@ parameters: - '#Method Ebook::NullIfEmpty\(\) has parameter \$elements with no type specified.#' - '#Method HttpInput::GetHttpVar\(\) has no return type specified.#' - '#Method HttpInput::GetHttpVar\(\) has parameter \$default with no type specified.#' - - # Ignore symbols that PHPStan can't find - - '#Constant EMAIL_SMTP_USERNAME not found.#' level: 8 paths: diff --git a/lib/Constants.php b/lib/Constants.php index fb9a6a2b..9ad6239f 100644 --- a/lib/Constants.php +++ b/lib/Constants.php @@ -7,7 +7,7 @@ use function Safe\strtotime; const SITE_STATUS_LIVE = 'live'; const SITE_STATUS_DEV = 'dev'; -define('SITE_STATUS', get_cfg_var('site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use define() and not const so we can use a function. +define('SITE_STATUS', get_cfg_var('se.site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use define() and not const so we can use a function. // No trailing slash on any of the below constants. if(SITE_STATUS == SITE_STATUS_LIVE){ @@ -35,14 +35,10 @@ const SORT_LENGTH = 'length'; const CAPTCHA_IMAGE_HEIGHT = 72; const CAPTCHA_IMAGE_WIDTH = 230; - const NO_REPLY_EMAIL_ADDRESS = 'admin@standardebooks.org'; const ADMIN_EMAIL_ADDRESS = 'admin@standardebooks.org'; const EDITOR_IN_CHIEF_EMAIL_ADDRESS = 'alex@standardebooks.org'; -// We don't define the email username/password in this file to -// 1) avoid a filesystem read when email isn't being used, and -// 2) allow scripts run by users not in the www-data group to succeed, otherwise they will not be able to open secret files on startup and crash -const POSTMARK_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/postmarkapp.com'; +define('EMAIL_SMTP_USERNAME', get_cfg_var('se.secrets.postmark.username')); const EMAIL_SMTP_HOST = 'smtp-broadcasts.postmarkapp.com'; const EMAIL_POSTMARK_STREAM_BROADCAST = 'the-standard-ebooks-newsletter'; @@ -87,6 +83,13 @@ const FA_FEE_PERCENT = 0.87; const SE_SUBJECTS = ['Adventure', 'Autobiography', 'Biography', 'Children’s', 'Comedy', 'Drama', 'Fantasy', 'Fiction', 'Horror', 'Memoir', 'Mystery', 'Nonfiction', 'Philosophy', 'Poetry', 'Satire', 'Science Fiction', 'Shorts', 'Spirituality', 'Tragedy', 'Travel']; +const GITHUB_IGNORED_REPOS = ['tools', 'manual', 'web']; // If we get GitHub push requests featuring these repos, silently ignore instead of returning an error. + +const GITHUB_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-github.log'; // Must be writable by `www-data` Unix user. +const POSTMARK_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-postmark.log'; // Must be writable by `www-data` Unix user. +const ZOHO_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-zoho.log'; // Must be writable by `www-data` Unix user. +const DONATIONS_LOG_FILE_PATH = '/var/log/local/donations.log'; // Must be writable by `www-data` Unix user. + define('PD_YEAR', intval(gmdate('Y')) - 96); define('PD_STRING', 'January 1, ' . (PD_YEAR + 1)); @@ -95,15 +98,3 @@ define('DONATION_ALERT_ON', DONATION_HOLIDAY_ALERT_ON || rand(1, 4) == 2); define('DONATION_DRIVE_ON', false); define('DONATION_DRIVE_COUNTER_ON', false); -const GITHUB_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/se-vcs-bot@github.com'; // Set in the GitHub organization global webhook settings. -const GITHUB_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-github.log'; // Must be writable by `www-data` Unix user. -const GITHUB_IGNORED_REPOS = ['tools', 'manual', 'web']; // If we get GitHub push requests featuring these repos, silently ignore instead of returning an error. - -const POSTMARK_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-postmark.log'; // Must be writable by `www-data` Unix user. - -const ZOHO_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/webhooks@zoho.com'; // Set in the GitHub organization global webhook settings. -const ZOHO_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-zoho.log'; // Must be writable by `www-data` Unix user. - -const FA_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/fracturedatlas.org'; -const DONATIONS_LOG_FILE_PATH = '/var/log/local/donations.log'; // Must be writable by `www-data` Unix user. - diff --git a/lib/Email.php b/lib/Email.php index fad1bdf3..84b41aa8 100644 --- a/lib/Email.php +++ b/lib/Email.php @@ -5,8 +5,6 @@ use PHPMailer\PHPMailer\Exception; use function Safe\define; use function Safe\file_get_contents; -define('EMAIL_SMTP_USERNAME', trim(file_get_contents(POSTMARK_SECRET_FILE_PATH))); - class Email{ public $To = ''; public $From = ''; diff --git a/scripts/process-pending-payments b/scripts/process-pending-payments index 7c74cc60..d453b6cc 100755 --- a/scripts/process-pending-payments +++ b/scripts/process-pending-payments @@ -34,7 +34,8 @@ $driver = null; $log = new Log(DONATIONS_LOG_FILE_PATH); $lastMonth = (new DateTime())->sub(new DateInterval('P45D')); // 45 days, a 15 day grace period before Patrons Circle members are dropped off $lastYear = (new DateTime())->sub(new DateInterval('P1Y')); -$faCredentials = explode("\n", trim(file_get_contents(FA_SECRET_FILE_PATH))); +$faUsername = get_cfg_var('se.secrets.fractured_atlas.username'); +$faPassword = get_cfg_var('se.secrets.fractured_atlas.password'); // Test donations // fa000cbf-af6f-4c14-8919-da6cf81a27ea Regular donation, patrons, public, recurring @@ -88,8 +89,8 @@ try{ $submitButton = $driver->wait(20, 250)->until(WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::xpath('//button[@type="submit"]'))); // Fill out and submit the form - $emailField->sendKeys($faCredentials[0]); - $passwordField->sendKeys($faCredentials[1]); + $emailField->sendKeys($faUsername); + $passwordField->sendKeys($faPassword); $submitButton->click(); } diff --git a/www/webhooks/github.php b/www/webhooks/github.php index 3d870f35..4c7b0d56 100644 --- a/www/webhooks/github.php +++ b/www/webhooks/github.php @@ -28,7 +28,7 @@ try{ $hashAlgorithm = $splitHash[0]; $hash = $splitHash[1]; - if(!hash_equals($hash, hash_hmac($hashAlgorithm, $post, preg_replace("/[\r\n]/ius", '', file_get_contents(GITHUB_SECRET_FILE_PATH))))){ + if(!hash_equals($hash, hash_hmac($hashAlgorithm, $post, get_cfg_var('se.secrets.github.se_vcs_bot.secret')))){ throw new Exceptions\InvalidCredentialsException(); } diff --git a/www/webhooks/postmark.php b/www/webhooks/postmark.php index 215198c3..a6bf9c1a 100644 --- a/www/webhooks/postmark.php +++ b/www/webhooks/postmark.php @@ -11,7 +11,7 @@ use function Safe\substr; $log = new Log(POSTMARK_WEBHOOK_LOG_FILE_PATH); try{ - $smtpUsername = trim(file_get_contents(POSTMARK_SECRET_FILE_PATH)); + $smtpUsername = get_cfg_var('se.secrets.postmark.username'); $log->Write('Received Postmark webhook.'); @@ -19,7 +19,7 @@ try{ throw new Exceptions\WebhookException('Expected HTTP POST.'); } - $apiKey = trim(file_get_contents(SITE_ROOT . '/config/secrets/webhooks@postmarkapp.com')); + $apiKey = get_cfg_var('se.secrets.postmark.api_key'); // Ensure this webhook actually came from Postmark if($apiKey != ($_SERVER['HTTP_X_SE_KEY'] ?? '')){ diff --git a/www/webhooks/zoho.php b/www/webhooks/zoho.php index 436f29da..0950de9f 100644 --- a/www/webhooks/zoho.php +++ b/www/webhooks/zoho.php @@ -23,7 +23,7 @@ try{ $post = file_get_contents('php://input'); // Validate the Zoho secret. - if(!hash_equals($_SERVER['HTTP_X_HOOK_SIGNATURE'], base64_encode(hash_hmac('sha256', $post, preg_replace("/[\r\n]/ius", '', file_get_contents(ZOHO_SECRET_FILE_PATH)), true)))){ + if(!hash_equals($_SERVER['HTTP_X_HOOK_SIGNATURE'], base64_encode(hash_hmac('sha256', $post, get_cfg_var('se.secrets.zoho.webhook_secret'), true)))){ throw new Exceptions\InvalidCredentialsException(); }