Files
Mitgliederverwaltung/tests/Unit/PermissionServiceTest.php
T
shahondin1624 d48e2b7d9d feat: v0.2.0 — backup system, self-update with Ed25519 signing, column pickers, import fixes
Major features:
- Full backup & restore system (JSON snapshots of all 20 tables + settings)
  - Web UI, REST API, OCC CLI commands, scheduled background job
- Self-update from Gitea releases with Ed25519 signature verification
- Configurable column visibility on all data tables (persisted via localStorage)

Fixes:
- NC admin group fallback for PermissionService (IGroupManager)
- Bundle import inline error correction (editable error rows)

New files: BackupService, BackupSettingsService, BackupController, BackupJob,
SelfUpdateService, 4 OCC commands, ColumnPicker component, Backup.vue,
Ed25519 signing scripts, signature verification tests (18 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:11:51 +02:00

436 lines
17 KiB
PHP

<?php
declare(strict_types=1);
namespace OCA\Mitgliederverwaltung\Tests\Unit;
use OCA\Mitgliederverwaltung\Db\Member;
use OCA\Mitgliederverwaltung\Db\MemberMapper;
use OCA\Mitgliederverwaltung\Db\Permission;
use OCA\Mitgliederverwaltung\Db\PermissionMapper;
use OCA\Mitgliederverwaltung\Service\PermissionService;
use OCA\Mitgliederverwaltung\Service\ValidationException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\IGroupManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class PermissionServiceTest extends TestCase {
private PermissionService $service;
private PermissionMapper&MockObject $permissionMapper;
private MemberMapper&MockObject $memberMapper;
private IGroupManager&MockObject $groupManager;
protected function setUp(): void {
$this->permissionMapper = $this->createMock(PermissionMapper::class);
$this->memberMapper = $this->createMock(MemberMapper::class);
$this->groupManager = $this->createMock(IGroupManager::class);
// By default, NC admin group check returns false so existing tests pass unchanged
$this->groupManager->method('isInGroup')->willReturn(false);
$this->service = new PermissionService(
$this->permissionMapper,
$this->memberMapper,
$this->groupManager
);
}
private function createPermission(string $level, ?string $stufenJson = null, bool $canSeeBanking = false): Permission {
$perm = new Permission();
$perm->setNcUserId('user1');
$perm->setLevel($level);
$perm->setAllowedStufenJson($stufenJson);
$perm->setCanSeeBanking($canSeeBanking);
$ref = new \ReflectionProperty($perm, 'id');
$ref->setAccessible(true);
$ref->setValue($perm, 1);
return $perm;
}
// ── getUserPermission() ────────────────────────────────────────
public function testGetUserPermissionReturnsPermission(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getUserPermission('user1');
$this->assertInstanceOf(Permission::class, $result);
$this->assertEquals('admin', $result->getLevel());
}
public function testGetUserPermissionReturnsNullWhenNotFound(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$result = $this->service->getUserPermission('unknown');
$this->assertNull($result);
}
// ── canAccess() ────────────────────────────────────────────────
public function testCanAccessReturnsTrueForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canAccess('user1'));
}
public function testCanAccessReturnsTrueForRead(): void {
$perm = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canAccess('user1'));
}
public function testCanAccessReturnsFalseForNone(): void {
$perm = $this->createPermission('none');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canAccess('user1'));
}
public function testCanAccessReturnsFalseForUnknownUser(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$this->assertFalse($this->service->canAccess('unknown'));
}
// ── canRead() ──────────────────────────────────────────────────
public function testCanReadReturnsTrueForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canRead('user1'));
}
public function testCanReadReturnsTrueForFull(): void {
$perm = $this->createPermission('full');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canRead('user1'));
}
public function testCanReadReturnsTrueForStufe(): void {
$perm = $this->createPermission('stufe');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canRead('user1'));
}
public function testCanReadReturnsTrueForRead(): void {
$perm = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canRead('user1'));
}
public function testCanReadReturnsFalseForNone(): void {
$perm = $this->createPermission('none');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canRead('user1'));
}
public function testCanReadReturnsFalseForUnknown(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$this->assertFalse($this->service->canRead('unknown'));
}
// ── canWrite() ─────────────────────────────────────────────────
public function testCanWriteReturnsTrueForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canWrite('user1'));
}
public function testCanWriteReturnsTrueForFull(): void {
$perm = $this->createPermission('full');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canWrite('user1'));
}
public function testCanWriteReturnsFalseForRead(): void {
$perm = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canWrite('user1'));
}
public function testCanWriteReturnsFalseForNone(): void {
$perm = $this->createPermission('none');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canWrite('user1'));
}
public function testCanWriteStufeAllowedMember(): void {
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$member = new Member();
$member->setStufeId(1);
$ref = new \ReflectionProperty($member, 'id');
$ref->setAccessible(true);
$ref->setValue($member, 10);
$this->memberMapper->method('findById')->willReturn($member);
$this->assertTrue($this->service->canWrite('user1', 10));
}
public function testCanWriteStufeDisallowedMember(): void {
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$member = new Member();
$member->setStufeId(5);
$ref = new \ReflectionProperty($member, 'id');
$ref->setAccessible(true);
$ref->setValue($member, 10);
$this->memberMapper->method('findById')->willReturn($member);
$this->assertFalse($this->service->canWrite('user1', 10));
}
public function testCanWriteStufeWithoutMemberId(): void {
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canWrite('user1'));
}
public function testCanWriteStufeWithDeletedMember(): void {
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->memberMapper->method('findById')
->willThrowException(new DoesNotExistException(''));
$this->assertFalse($this->service->canWrite('user1', 999));
}
// ── canWriteStufe() ────────────────────────────────────────────
public function testCanWriteStufeReturnsTrueForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canWriteStufe('user1', 5));
}
public function testCanWriteStufeReturnsTrueForFull(): void {
$perm = $this->createPermission('full');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canWriteStufe('user1', 5));
}
public function testCanWriteStufeReturnsTrueForAllowedStufe(): void {
$perm = $this->createPermission('stufe', '[1, 5]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canWriteStufe('user1', 5));
}
public function testCanWriteStufeReturnsFalseForDisallowedStufe(): void {
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canWriteStufe('user1', 5));
}
public function testCanWriteStufeReturnsFalseForRead(): void {
$perm = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canWriteStufe('user1', 5));
}
// ── isAdmin() ──────────────────────────────────────────────────
public function testIsAdminReturnsTrueForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->isAdmin('user1'));
}
public function testIsAdminReturnsFalseForFull(): void {
$perm = $this->createPermission('full');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->isAdmin('user1'));
}
public function testIsAdminReturnsFalseForUnknown(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$this->assertFalse($this->service->isAdmin('unknown'));
}
// ── canSeeBanking() ────────────────────────────────────────────
public function testCanSeeBankingReturnsTrue(): void {
$perm = $this->createPermission('full', null, true);
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertTrue($this->service->canSeeBanking('user1'));
}
public function testCanSeeBankingReturnsFalse(): void {
$perm = $this->createPermission('full', null, false);
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->assertFalse($this->service->canSeeBanking('user1'));
}
public function testCanSeeBankingReturnsFalseForUnknown(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$this->assertFalse($this->service->canSeeBanking('unknown'));
}
// ── getVisibleStufen() ─────────────────────────────────────────
public function testGetVisibleStufenReturnsNullForAdmin(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getVisibleStufen('user1');
$this->assertNull($result);
}
public function testGetVisibleStufenReturnsNullForFull(): void {
$perm = $this->createPermission('full');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getVisibleStufen('user1');
$this->assertNull($result);
}
public function testGetVisibleStufenReturnsNullForRead(): void {
$perm = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getVisibleStufen('user1');
$this->assertNull($result);
}
public function testGetVisibleStufenReturnsIdsForStufe(): void {
$perm = $this->createPermission('stufe', '[1, 3]');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getVisibleStufen('user1');
$this->assertEquals([1, 3], $result);
}
public function testGetVisibleStufenReturnsEmptyForNone(): void {
$perm = $this->createPermission('none');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$result = $this->service->getVisibleStufen('user1');
$this->assertEquals([], $result);
}
public function testGetVisibleStufenReturnsEmptyForUnknown(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$result = $this->service->getVisibleStufen('unknown');
$this->assertEquals([], $result);
}
// ── getAllPermissions() ─────────────────────────────────────────
public function testGetAllPermissions(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findAll')->willReturn([$perm]);
$result = $this->service->getAllPermissions();
$this->assertCount(1, $result);
}
// ── setPermission() ────────────────────────────────────────────
public function testSetPermissionCreatesNew(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$perm = $this->createPermission('admin');
$this->permissionMapper->method('insert')->willReturn($perm);
$result = $this->service->setPermission('user1', 'admin');
$this->assertInstanceOf(Permission::class, $result);
}
public function testSetPermissionUpdatesExisting(): void {
$existing = $this->createPermission('read');
$this->permissionMapper->method('findByUserId')->willReturn($existing);
$updated = $this->createPermission('admin');
$this->permissionMapper->method('update')->willReturn($updated);
$result = $this->service->setPermission('user1', 'admin');
$this->assertInstanceOf(Permission::class, $result);
}
public function testSetPermissionWithStufen(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
$perm = $this->createPermission('stufe', '[1, 2]');
$this->permissionMapper->method('insert')->willReturn($perm);
$result = $this->service->setPermission('user1', 'stufe', [1, 2]);
$this->assertInstanceOf(Permission::class, $result);
}
public function testSetPermissionThrowsOnInvalidLevel(): void {
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Ungueltiges Berechtigungslevel');
$this->service->setPermission('user1', 'superadmin');
}
// ── removePermission() ─────────────────────────────────────────
public function testRemovePermission(): void {
$perm = $this->createPermission('admin');
$this->permissionMapper->method('findByUserId')->willReturn($perm);
$this->permissionMapper->expects($this->once())->method('delete');
$this->service->removePermission('user1');
}
public function testRemovePermissionNoOpWhenNotFound(): void {
$this->permissionMapper->method('findByUserId')
->willThrowException(new DoesNotExistException(''));
// Should not throw
$this->service->removePermission('unknown');
$this->assertTrue(true);
}
}