Phase 2: verify per-user exports, refuse SMB without the native extension, matrix user CI
CI / unit (8.2) (push) Has been cancelled
CI / unit (8.3) (push) Has been cancelled
CI / unit (8.4) (push) Has been cancelled
CI / psalm (push) Has been cancelled
CI / integration (mariadb, 32) (push) Has been cancelled
CI / integration (mariadb, 33) (push) Has been cancelled
CI / integration (mariadb, 34) (push) Has been cancelled
CI / integration (mariadb, 35) (push) Has been cancelled
CI / integration (pgsql, 32) (push) Has been cancelled
CI / integration (pgsql, 33) (push) Has been cancelled
CI / integration (pgsql, 34) (push) Has been cancelled
CI / integration (pgsql, 35) (push) Has been cancelled
CI / integration (sqlite, 32) (push) Has been cancelled
CI / integration (sqlite, 33) (push) Has been cancelled
CI / integration (sqlite, 34) (push) Has been cancelled
CI / integration (sqlite, 35) (push) Has been cancelled
CI / integration-targets (push) Has been cancelled
CI / integration-user (32) (push) Has been cancelled
CI / integration-user (33) (push) Has been cancelled
CI / integration-user (34) (push) Has been cancelled
CI / integration-user (35) (push) Has been cancelled
CI / integration-full-restore (push) Has been cancelled

backup:verify accepts a user export path (users/<uid>/<export>): every blob its manifest references
is checked the same way as for a snapshot, shallow or --deep.

The SMB backend is refused at backup:target:add when the native smbclient PECL extension is not
loaded, instead of registering and then failing the first backup with "Seek failed": with only the
smbclient binary files_external falls back to a shell stream that cannot seek.

The per-user integration job now runs on Nextcloud 32-35, not just 35: it calls user_migration's
internal UserMigrationService, whose API may change between versions.
This commit is contained in:
2026-10-06 03:47:02 +02:00
parent c9f82a79e4
commit d70a869070
5 changed files with 66 additions and 8 deletions
+6
View File
@@ -53,6 +53,12 @@ final class TargetService {
if (!preg_match('/^[A-Za-z0-9][A-Za-z0-9 _.-]{0,63}$/', $name)) {
throw new \InvalidArgumentException('Name: letters, digits, space, _ . - (max 64)');
}
// Without the native extension files_external falls back to the smbclient binary, which
// registers fine but cannot seek: the first backup then fails with "Seek failed". Refuse
// up front instead of letting the admin find out from a failed run.
if ($backend === 'smb' && !extension_loaded('smbclient')) {
throw new \InvalidArgumentException('The SMB backend needs the PHP smbclient extension (pecl install smbclient); the smbclient binary alone cannot seek and every backup would fail');
}
try {
$this->mapper->findByName($name);
throw new \InvalidArgumentException("A target named '$name' already exists");