mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-12 06:48:55 +00:00
e187513cdd
`env()` recognises the words "true" and "false" and returns everything
else as the string it was — and every non-empty string is truthy in PHP.
So `(bool) env('PROJECTSEND_CAPTCHA_DISABLED')` read all of these as "yes,
disabled":
PROJECTSEND_CAPTCHA_DISABLED=no
PROJECTSEND_CAPTCHA_DISABLED=off
PROJECTSEND_CAPTCHA_DISABLED=fasle
An operator who meant to say no took the bot protection off their login
and registration forms and had nothing to tell them so — the setting
screen still shows the CAPTCHA configured, because this is the escape
hatch that runs ahead of it.
For most settings the cast is a shrug: somebody notices the feature is on
and fixes the line. It stops being a shrug when the wrong answer is the
unsafe one, and this is one of those. EnvFlag lists what counts as yes —
`true` and `1`, either case, either type — and reads everything else,
recognised or not, as no. A value typed as `disabled` turns nothing off:
a configuration mistake to be found rather than guessed at.
Found while fixing the same bug in a new cloud-modules flag, where the
unsafe direction was publishing a customer's files rather than dropping a
CAPTCHA. Two of the four remaining `(bool) env()` casts are left alone on
purpose: a wrong S3 path-style value breaks storage loudly, and the
migration tool's direct mode defaults to true anyway, so neither fails
into an unsafe state.
205 lines
8.7 KiB
PHP
205 lines
8.7 KiB
PHP
<?php
|
|
|
|
use App\Modules\Platform\Capabilities\Edition;
|
|
use App\Support\EnvFlag;
|
|
|
|
return [
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Edition
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Which edition this installation runs as. Edition is configuration, not a
|
|
| code branch: every behavioural difference between editions must flow
|
|
| through the capability registry, never through ad-hoc edition checks.
|
|
|
|
|
| Supported: "community", "cloud"
|
|
|
|
|
*/
|
|
|
|
'edition' => Edition::from((string) env('PROJECTSEND_EDITION', 'community')),
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Uploads
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Where a chunked upload's parts wait while the transfer is running,
|
|
| before they are assembled onto the storage disk. Leave this unset:
|
|
| it exists so the test suite can give each parallel worker its own
|
|
| directory, since parts are real files on a real path rather than a
|
|
| faked disk, and session ids restart at 1 in every worker's database.
|
|
|
|
|
*/
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Platform seats
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| How many staff accounts and how many clients this installation may
|
|
| hold. Unset means unlimited, which is every self-hosted install: this
|
|
| exists for a managed one, where the operator sold a number and the
|
|
| application is the only process that can actually count against it.
|
|
|
|
|
| An operator stating the installation's own limit is not the same as
|
|
| the application inventing a plan tier — the distinction config/api.php
|
|
| draws when it declines to key a rate limit off billing. Nothing here
|
|
| knows what a plan is; it accepts a number and refuses to exceed it.
|
|
|
|
|
*/
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Capabilities this installation has been told it may not use
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Comma-separated capability keys, subtracted from what the edition
|
|
| grants. Only ever subtracted: nothing here can switch a capability on,
|
|
| because a variable that could would put the hosted edition's screens
|
|
| one line of .env away on every self-hosted install.
|
|
|
|
|
| For a managed installation whose plan does not include something its
|
|
| edition otherwise has -- branding.customize on a free plan is the case
|
|
| this was built for. Unknown keys are ignored rather than fatal: the
|
|
| variable outlives both the plan that wrote it and the release that
|
|
| named the key, and an instance refusing to boot over a stale one would
|
|
| be an outage on upgrade day.
|
|
|
|
|
*/
|
|
|
|
'capabilities_disabled' => env('PROJECTSEND_CAPABILITIES_DISABLED'),
|
|
|
|
'platform' => [
|
|
'max_staff_users' => env('PROJECTSEND_PLATFORM_MAX_STAFF_USERS'),
|
|
'max_clients' => env('PROJECTSEND_PLATFORM_MAX_CLIENTS'),
|
|
|
|
// Seeded into Setting::TwoFactorEnforcement on first boot and never
|
|
// afterwards — see SeedSettingsCommand. Here rather than read from
|
|
// env() at the point of use, because config:cache stops .env being
|
|
// read at all and that is how TRUSTED_PROXIES came to silently do
|
|
// nothing.
|
|
'two_factor_enforcement' => env('PROJECTSEND_TWO_FACTOR_ENFORCEMENT'),
|
|
],
|
|
|
|
'uploads' => [
|
|
'parts_path' => env('UPLOAD_PARTS_PATH'),
|
|
],
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| How downloads leave the server
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Uploads live outside the web root, so PHP authorizes every download
|
|
| before any byte moves. What differs is what happens next: PHP can
|
|
| stream the file itself, or hand the web server a header naming the
|
|
| file and let it do the work. The header is faster and each server
|
|
| spells it differently — a server that does not recognise the one it
|
|
| is sent serves the empty body instead, which is a 0-byte download.
|
|
|
|
|
| 'auto' (the default) uses nginx's X-Accel-Redirect when the server
|
|
| says it is nginx, and PHP streaming otherwise. 'nginx', 'xsendfile'
|
|
| (Apache with mod_xsendfile, or LiteSpeed) and 'php' state it
|
|
| outright. Read here rather than through env() elsewhere, so that
|
|
| `php artisan config:cache` does not silently blank it.
|
|
|
|
|
*/
|
|
|
|
'file_delivery' => env('PROJECTSEND_FILE_DELIVERY', 'auto'),
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Chunked upload part size (MB)
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Each resumable-upload part travels as one request of this size;
|
|
| web-server/PHP body limits only need to cover a single part.
|
|
|
|
|
*/
|
|
|
|
'upload_part_size_mb' => 20,
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CAPTCHA
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Two things live here rather than in the settings store, for two
|
|
| different reasons.
|
|
|
|
|
| "disabled" is an escape hatch: a wrong secret key cannot lock anybody
|
|
| out (see CaptchaResult), but an operator who has managed it some other
|
|
| way needs a fix that touches no database and needs no working login.
|
|
|
|
|
| The managed keys are the platform's own, applied to every tenant on
|
|
| cloud and absent everywhere else. In config rather than the tenant
|
|
| database so a database dump never carries our credential, and so
|
|
| rotating it is one fleet-wide change instead of a migration. They do
|
|
| nothing without Capability::CaptchaManagedKeys.
|
|
|
|
|
*/
|
|
|
|
'captcha' => [
|
|
// Read strictly rather than cast: `env()` returns anything it does
|
|
// not recognise as the string it was, and every non-empty string
|
|
// is truthy — so `(bool)` would read `PROJECTSEND_CAPTCHA_DISABLED=no`
|
|
// as "yes, disabled" and quietly take the bot protection off the
|
|
// login and registration forms. See App\Support\EnvFlag.
|
|
'disabled' => EnvFlag::isTrue(env('PROJECTSEND_CAPTCHA_DISABLED', false)),
|
|
|
|
'managed' => [
|
|
'provider' => env('PROJECTSEND_CAPTCHA_MANAGED_PROVIDER'),
|
|
'site_key' => env('PROJECTSEND_CAPTCHA_MANAGED_SITE_KEY'),
|
|
'secret_key' => env('PROJECTSEND_CAPTCHA_MANAGED_SECRET_KEY'),
|
|
'score_threshold' => (float) env('PROJECTSEND_CAPTCHA_MANAGED_SCORE_THRESHOLD', 0.5),
|
|
],
|
|
],
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Release identity
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Per-release facts that ship with the code. Not settings: they never
|
|
| vary per install or tenant.
|
|
|
|
|
*/
|
|
|
|
// How long a request waits for another one that is already rendering
|
|
// the same thumbnail or preview, before giving up rather than
|
|
// decoding the same image a second time. See ThumbnailGenerator.
|
|
// A slow disk or a large source wants longer than the default 15.
|
|
'rendition_lock_wait_seconds' => env('PROJECTSEND_RENDITION_LOCK_WAIT_SECONDS'),
|
|
|
|
'version' => '2.4.0',
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Official links
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
// Read through App\Modules\Platform\OfficialLinks rather than
|
|
// directly: which of the two front doors "website" means, and whether
|
|
// the donation link is offered at all, both depend on the edition.
|
|
'links' => [
|
|
'website' => 'https://www.projectsend.org/',
|
|
// The hosted service's own front door. A managed installation
|
|
// links here instead — including from the "Powered by" line on
|
|
// client-facing pages and outgoing email.
|
|
'website_cloud' => 'https://www.projectsend.cloud/',
|
|
// Where this code lives, and the same repository
|
|
// CheckForUpdatesCommand asks for the latest release. v1 remains
|
|
// available at github.com/projectsend/legacy.
|
|
'source' => 'https://github.com/projectsend/projectsend',
|
|
'open_collective' => 'https://opencollective.com/projectsend',
|
|
// Kept identical to the invitation update.sh prints when an update
|
|
// finishes — the two are the same offer, made in the terminal and
|
|
// then again on the screen the administrator lands on.
|
|
'discord' => 'https://discord.gg/VT9n6cyvXT',
|
|
],
|
|
|
|
];
|