mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-18 09:35:07 +00:00
7119435c3c
The button was disabled on a library that had already been scanned once, which is most of the time and exactly when somebody would press it — after updating definitions, say. It now re-checks everything rather than only what was never looked at, which is what its name says. A rescan keeps each file available until its new verdict arrives, so a full pass takes nothing offline. The two states it skips are a file already waiting for its first verdict and one whose bytes are gone. It is disabled for two honest reasons now — scanning is off, or a scan is already running — and says which. Results are green, amber and red: checked and fine, checked and could not be read, checked and something was found. The badge gained a warning variant to say the middle one, matching the amber the warning alert already uses; before this a missing file wore the same red as a virus. A file found missing is also stamped with the time it was checked, so it appears in the Activity list. It is a verdict like any other, and without the stamp it was decided somewhere nobody could see.
78 lines
3.0 KiB
PHP
78 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Modules\Files\Console;
|
|
|
|
use App\Modules\Audit\Action;
|
|
use App\Modules\Audit\ActivityLogger;
|
|
use App\Modules\Files\MissingFileScanner;
|
|
use App\Modules\Files\Models\File;
|
|
use App\Modules\Files\Scanning\NotScannedReason;
|
|
use App\Modules\Files\Scanning\ScanningConfig;
|
|
use App\Modules\Files\Scanning\ScanStatus;
|
|
use Illuminate\Console\Command;
|
|
|
|
/**
|
|
* Checks daily that the files this installation lists are actually there.
|
|
*
|
|
* Its own command rather than part of scanning, because a missing file is
|
|
* not a virus question and an installation with no scanner has exactly
|
|
* the same problem. It was only ever noticed when something tried to read
|
|
* the bytes — a download, or a scan — which means the first person to
|
|
* find out was a client clicking a link.
|
|
*
|
|
* Recovery is part of the job: storage comes back, and a library that
|
|
* kept insisting every file was gone would be its own bug.
|
|
*/
|
|
class CheckMissingFilesCommand extends Command
|
|
{
|
|
protected $signature = 'projectsend:check-missing-files';
|
|
|
|
protected $description = 'Check that every file in the database is still on disk (runs daily)';
|
|
|
|
public function handle(MissingFileScanner $scanner, ActivityLogger $activity, ScanningConfig $scanning): int
|
|
{
|
|
$gone = $scanner->scan();
|
|
$newlyGone = 0;
|
|
|
|
foreach (array_chunk($gone, 200) as $chunk) {
|
|
foreach (File::query()->whereIn('id', $chunk)->where('scan_status', '!=', ScanStatus::Missing)->get() as $file) {
|
|
// Stamped like any other verdict: this is the moment the
|
|
// file was last looked at, and without it a missing file
|
|
// never appears in the Activity list — which is exactly
|
|
// where somebody watching would look for it.
|
|
$file->forceFill([
|
|
'scan_status' => ScanStatus::Missing,
|
|
'scan_note' => null,
|
|
'scanned_at' => now(),
|
|
])->save();
|
|
|
|
$activity->logSystem(Action::FileMissing, ['id' => $file->id, 'name' => $file->name]);
|
|
$newlyGone++;
|
|
}
|
|
}
|
|
|
|
$back = $scanner->recovered();
|
|
|
|
foreach (array_chunk($back, 200) as $chunk) {
|
|
// Back to the start rather than to whatever it was before:
|
|
// nothing here knows what the scanner had decided about bytes
|
|
// that have since been away, and re-checking them is cheap
|
|
// next to trusting a verdict about a file that left.
|
|
File::query()->whereIn('id', $chunk)->update($scanning->enabled()
|
|
? ['scan_status' => ScanStatus::Pending->value, 'scan_note' => null]
|
|
: ['scan_status' => ScanStatus::NotScanned->value, 'scan_note' => NotScannedReason::BeforeScanning->value]);
|
|
}
|
|
|
|
$this->info(sprintf(
|
|
'%d file(s) are missing from storage (%d newly), %d came back.',
|
|
count($gone),
|
|
$newlyGone,
|
|
count($back),
|
|
));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
}
|