Add nextcloud connections
continuous-integration/drone/push Build was killed Details

This commit is contained in:
philipp lang 2024-07-13 22:30:34 +02:00
parent 74867cb09f
commit 2b48f42734
5 changed files with 204 additions and 34 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace App\Fileshare\ConnectionTypes;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;
use League\Flysystem\Filesystem;
use League\Flysystem\WebDAV\WebDAVAdapter;
use Sabre\DAV\Client;
class NextcloudConnection extends OwncloudConnection
{
public function check(): bool
{
try {
$response = Http::withoutVerifying()
->withBasicAuth($this->user, $this->password)
->withHeaders(['OCS-APIRequest' => 'true'])
->acceptJson()
->get($this->baseUrl . '/ocs/v2.php/cloud/capabilities');
return $response->ok();
} catch (ConnectionException $e) {
return false;
}
}
public static function title(): string
{
return 'Nextcloud';
}
public function getFilesystem(): FilesystemAdapter
{
$adapter = new WebDAVAdapter(new Client([
'baseUri' => $this->baseUrl . '/remote.php/dav/files/' . $this->user,
'userName' => $this->user,
'password' => $this->password,
]), '/remote.php/dav/files/' . $this->user);
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
}
}

View File

@ -2,6 +2,7 @@
namespace Tests\Fileshare;
use App\Fileshare\ConnectionTypes\NextcloudConnection;
use App\Fileshare\ConnectionTypes\OwncloudConnection;
use App\Fileshare\Models\Fileshare;
use Tests\FileshareTestCase;
@ -10,11 +11,11 @@ class FileshareFilesActionTest extends FileshareTestCase
{
public function testItGetsFilesForAConnection(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ieH2auj5AhKaengoD4Taeng9o')
->withDirs('badenpowell', ['/pictures', '/lala']);
$connection = Fileshare::factory()
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'ieH2auj5AhKaengoD4Taeng9o', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), [
@ -31,11 +32,11 @@ class FileshareFilesActionTest extends FileshareTestCase
public function testItGetsSubdirectories(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ieH2auj5AhKaengoD4Taeng9o')
->withDirs('badenpowell', ['/pictures', '/lala', '/lala/dd', '/lala/ff']);
$connection = Fileshare::factory()
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'ieH2auj5AhKaengoD4Taeng9o', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/pictures'])->assertJsonCount(0, 'data');
@ -51,11 +52,11 @@ class FileshareFilesActionTest extends FileshareTestCase
public function testItGetsSubdirectoriesOfSubdirectory(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ieH2auj5AhKaengoD4Taeng9o')
->withDirs('badenpowell', ['/lala', '/lala/dd', '/lala/dd/ee']);
$connection = Fileshare::factory()
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'ieH2auj5AhKaengoD4Taeng9o', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/lala/dd'])
@ -67,14 +68,51 @@ class FileshareFilesActionTest extends FileshareTestCase
public function testItGetsFilesWithDot(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ieH2auj5AhKaengoD4Taeng9o')
->withDirs('badenpowell', ['/1. aa']);
$connection = Fileshare::factory()
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'ieH2auj5AhKaengoD4Taeng9o', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/'])
->assertJsonPath('data.0.name', '1. aa');
}
public function testItGetsFilesFromNextcloudConnection(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ohke5ko7ohBae8aiPh7fuu6ka')
->withDirs('badenpowell', ['/pictures', '/lala']);
$connection = Fileshare::factory()
->type(NextcloudConnection::from(['user' => 'badenpowell', 'password' => 'ohke5ko7ohBae8aiPh7fuu6ka', 'base_url' => env('TEST_NEXTCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), [
'parent' => null,
])
->assertJsonCount(2, 'data')
->assertJsonPath('data.0.name', 'lala')
->assertJsonPath('data.0.path', '/lala')
->assertJsonPath('data.0.parent', '/')
->assertJsonPath('data.1.name', 'pictures')
->assertJsonPath('data.1.path', '/pictures')
->assertJsonPath('data.1.parent', '/');
}
public function testItGetsNextcloudSubdirectoriesOfSubdirectory(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'ailiew7AhshiWae4va9OphieN')
->withDirs('badenpowell', ['/lala', '/lala/dd', '/lala/dd/ee']);
$connection = Fileshare::factory()
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'ailiew7AhshiWae4va9OphieN', 'base_url' => env('TEST_NEXTCLOUD_DOMAIN')]))
->create();
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/lala/dd'])
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.name', 'ee')
->assertJsonPath('data.0.path', '/lala/dd/ee')
->assertJsonPath('data.0.parent', '/lala/dd');
}
}

View File

@ -2,6 +2,7 @@
namespace Tests\Fileshare;
use App\Fileshare\ConnectionTypes\NextcloudConnection;
use App\Fileshare\ConnectionTypes\OwncloudConnection;
use App\Fileshare\Models\Fileshare;
use Tests\FileshareTestCase;
@ -10,7 +11,7 @@ class FileshareStoreActionTest extends FileshareTestCase
{
public function testItStoresAConnection(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret');
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'secret');
$this->post(route('fileshare.store'), [
'name' => 'Lala',
@ -58,4 +59,25 @@ class FileshareStoreActionTest extends FileshareTestCase
]
])->assertJsonValidationErrors(['name' => 'Name ist erforderlich.']);
}
public function testItStoresNextcloudConnection(): void
{
$this->withoutExceptionHandling()->login()->loginNami()->withUser('badenpowell', 'uaLeitu3eecoweePhaeGei3Oa');
$this->post(route('fileshare.store'), [
'name' => 'Lala',
'type' => NextcloudConnection::class,
'config' => [
'user' => 'badenpowell',
'password' => 'uaLeitu3eecoweePhaeGei3Oa',
'base_url' => env('TEST_NEXTCLOUD_DOMAIN'),
]
])->assertOk();
$connection = Fileshare::firstOrFail();
$this->assertEquals('badenpowell', $connection->type->user);
$this->assertEquals('uaLeitu3eecoweePhaeGei3Oa', $connection->type->password);
$this->assertEquals(env('TEST_NEXTCLOUD_DOMAIN'), $connection->type->baseUrl);
$this->assertEquals('Lala', $connection->name);
}
}

View File

@ -6,7 +6,8 @@ services:
ports:
- 5566:8080
depends_on:
- mariadb
mariadb:
condition: service_healthy
environment:
- OWNCLOUD_DOMAIN=http://localhost:5566
- OWNCLOUD_TRUSTED_DOMAINS=
@ -45,3 +46,36 @@ services:
retries: 5
volumes:
- ./oc_tmp/db:/var/lib/mysql
nextclouddb:
image: mariadb:10.6
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-u', 'root', '--password=secret']
interval: 10s
timeout: 5s
retries: 5
volumes:
- ./oc_tmp/ncdb:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_PASSWORD=secret
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
app:
image: nextcloud
restart: always
depends_on:
nextclouddb:
condition: service_healthy
ports:
- 5567:80
environment:
- MYSQL_PASSWORD=secret
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=nextclouddb
- NEXTCLOUD_ADMIN_USER=admin
- NEXTCLOUD_ADMIN_PASSWORD=admin
- NEXTCLOUD_TRUSTED_DOMAINS=

View File

@ -2,16 +2,16 @@
namespace Tests;
use App\Fileshare\ConnectionTypes\ConnectionType;
use App\Fileshare\ConnectionTypes\NextcloudConnection;
use App\Fileshare\ConnectionTypes\OwncloudConnection;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\DirectoryAttributes;
use League\Flysystem\Filesystem;
use League\Flysystem\WebDAV\WebDAVAdapter;
use Sabre\DAV\Client;
use Throwable;
abstract class FileshareTestCase extends TestCase
{
@ -29,25 +29,42 @@ abstract class FileshareTestCase extends TestCase
{
parent::setUp();
foreach ($this->http()->get('/ocs/v1.php/cloud/users?format=json')->json('ocs.data.users') as $user) {
foreach ($this->http(OwncloudConnection::class)->get('/ocs/v1.php/cloud/users?format=json')->json('ocs.data.users') as $user) {
if ($user === $this->adminUser) {
continue;
}
$this->http()->delete('/ocs/v1.php/cloud/users/' . $user);
$this->http(OwncloudConnection::class)->delete('/ocs/v1.php/cloud/users/' . $user);
}
foreach ($this->http(NextcloudConnection::class)->get('/ocs/v2.php/cloud/users')->json('ocs.data.users') as $user) {
if ($user === $this->adminUser) {
continue;
}
$this->http(NextcloudConnection::class)->delete('/ocs/v2.php/cloud/users/' . $user);
}
}
public function withOwncloudUser(string $username, string $password): self
public function withUser(string $username, string $password): self
{
$this->passwords[$username] = $password;
$this->http()->asForm()->post('/ocs/v1.php/cloud/users?format=json', ['password' => $password, 'userid' => $username]);
$this->http(OwncloudConnection::class)->asForm()->post('/ocs/v1.php/cloud/users?format=json', ['password' => $password, 'userid' => $username]);
$this->http(NextcloudConnection::class)->post('/ocs/v2.php/cloud/users', ['password' => $password, 'userid' => $username]);
return $this;
}
private function http(): PendingRequest
/**
* @param class-string<ConnectionType> $connection
*/
private function http(string $connection): PendingRequest
{
return Http::withOptions(['base_uri' => env('TEST_OWNCLOUD_DOMAIN')])->withBasicAuth($this->adminUser, $this->adminPassword)->acceptJson();
if ($connection === OwncloudConnection::class) {
return Http::withOptions(['base_uri' => env('TEST_OWNCLOUD_DOMAIN')])->withBasicAuth($this->adminUser, $this->adminPassword)->acceptJson();
}
if ($connection === NextcloudConnection::class) {
return Http::withOptions(['base_uri' => env('TEST_NEXTCLOUD_DOMAIN')])->withHeaders(['OCS-APIRequest' => 'true'])->withBasicAuth($this->adminUser, $this->adminPassword)->acceptJson();
}
}
/**
@ -55,30 +72,45 @@ abstract class FileshareTestCase extends TestCase
*/
protected function withDirs(string $username, array $dirs): self
{
$adapter = $this->adapter($username);
foreach ([NextcloudConnection::class, OwncloudConnection::class] as $connection) {
$adapter = $this->adapter($username, $connection);
foreach ($adapter->directories('/') as $directory) {
$adapter->deleteDirectory($directory);
}
foreach ($adapter->directories('/') as $directory) {
$adapter->deleteDirectory($directory);
}
foreach ($adapter->files('/') as $file) {
$adapter->delete($file);
}
foreach ($adapter->files('/') as $file) {
$adapter->delete($file);
}
foreach ($dirs as $dir) {
$adapter->makeDirectory($dir);
foreach ($dirs as $dir) {
$adapter->makeDirectory($dir);
}
}
return $this;
}
private function adapter(string $username): FilesystemAdapter
/**
* @param class-string<ConnectionType> $connection
*/
private function adapter(string $username, string $connection): FilesystemAdapter
{
$adapter = new WebDAVAdapter(new Client([
'baseUri' => env('TEST_OWNCLOUD_DOMAIN') . '/remote.php/dav/files/' . $username,
'userName' => $username,
'password' => $this->passwords[$username],
]), '/remote.php/dav/files/' . $username);
if ($connection === OwncloudConnection::class) {
$adapter = new WebDAVAdapter(new Client([
'baseUri' => env('TEST_OWNCLOUD_DOMAIN') . '/remote.php/dav/files/' . $username,
'userName' => $username,
'password' => $this->passwords[$username],
]), '/remote.php/dav/files/' . $username);
}
if ($connection === NextcloudConnection::class) {
$adapter = new WebDAVAdapter(new Client([
'baseUri' => env('TEST_NEXTCLOUD_DOMAIN') . '/remote.php/dav/files/' . $username,
'userName' => $username,
'password' => $this->passwords[$username],
]), '/remote.php/dav/files/' . $username);
}
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
}