Files
ignacionelson 6e47d76ba6 ProjectSend 2.0.0
Client file sharing, rebuilt from the ground up: a private area per
client, resumable uploads, folders, groups and categories, sharing with
expiry dates and download limits, comments, file versions, an activity
log, a REST API, and sixteen languages.

This repository begins here. ProjectSend 2 was developed privately, and
that development history is not published — the previous generation
remains available, with its own history, at projectsend/legacy.

Free software under the GNU General Public License v2, or (at your
option) any later version.
2026-08-14 01:38:12 -03:00

71 lines
2.6 KiB
PHP

<?php
declare(strict_types=1);
use App\Http\Middleware\ValidateCsrfToken;
use App\Models\User;
use Symfony\Component\HttpFoundation\Cookie;
/**
* The CSRF cookie is named after this installation, not after the
* framework.
*
* Cookies are scoped by host and ignore the port, so two Laravel
* applications on one hostname share every cookie name they have in
* common. With the framework's hardcoded `XSRF-TOKEN` that means a
* staging copy on another port — or any neighbouring Laravel app —
* overwrites this installation's token, and every write here starts
* failing with a 419.
*
* That failure is horrible to diagnose from the inside: the session is
* untouched, so reads keep working and only writes break, and a 419 reads
* as "your session expired" when the session is perfectly alive.
* Reloading appears to fix it, right up until the neighbour answers
* another request.
*/
beforeEach(function () {
User::factory()->create();
});
test('the csrf cookie is named after this installation', function () {
config()->set('session.xsrf_cookie', 'projectsend_cloud_xsrf');
$response = $this->get('/login');
// getName(), not pluck('name') — Symfony's Cookie exposes a method, and
// plucking a property that isn't there yields a list of nulls that
// quietly fails to contain anything at all.
$names = array_map(
static fn (Cookie $cookie): string => $cookie->getName(),
$response->headers->getCookies(),
);
expect($names)
->toContain('projectsend_cloud_xsrf')
// The name the framework would have used, and the whole problem.
->not->toContain('XSRF-TOKEN');
});
test('the name is derived from the session cookie, so nobody has to set two', function () {
// config/session.php derives it; this asserts the shape that derivation
// produces rather than re-deriving it here.
expect(config('session.xsrf_cookie'))
->toBe(str_replace('_session', '', (string) config('session.cookie')).'_xsrf');
});
test('it falls back to the framework name rather than an empty cookie', function () {
config()->set('session.xsrf_cookie', '');
expect(ValidateCsrfToken::cookieName())->toBe('XSRF-TOKEN');
});
test('the layout tells the frontend which cookie to read', function () {
config()->set('session.xsrf_cookie', 'projectsend_cloud_xsrf');
// Nothing on the client can derive this name, so the page has to carry
// it — and if the tag and the cookie ever disagree, every write 419s.
$this->get('/login')
->assertOk()
->assertSee('<meta name="xsrf-cookie" content="projectsend_cloud_xsrf">', false);
});