Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/DIMOC-208/fileupload-fe #119

Merged
merged 16 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,4 @@
.errorMessage {
color: var(--color-error);
}

Binary file added docs/assets/Instellingen_voor_opslag.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion docs/developers/aan-de-slag-met-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ npm run lint
Voor de backend is dat:

```cli
phpcs
phpcs [filename]
```

Hiervoor moet php code sniffer geïnstalleerd zijn. [Zie hier](https://dev.to/xxzeroxx/phpcs-php-code-sniffer-59f4) de handleiding ervoor

Voor beide geldt dat het aantal acceptabele errors 0 is.

## Voor stabilliteit gebruiken we unit tests
Expand Down
11 changes: 8 additions & 3 deletions docs/developers/de-opencatalogi-app-toevoegen-aan-nextcloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ Klik op het icoontje van OpenCatalogi en je zit in de app!

![OpenCatalogi instellingen](../assets/oc_instellingen_1.png)

* Vul bij 'instellingen' -> 'configuratie' de benodigde gegevens in:
* Een MongoDB API met sleutel en clusternaam.
* Voor het activeren van het zoekendpoint: een Elasticsearch met API key en index.
* Vul bij 'settings' -> 'configuratie' de benodigde gegevens in voor opslag:

* default instellingen voor opslag (optioneel)
* DRC or ORC (optioneel)
* Een MongoDB API met sleutel en clusternaam(optioneel).
* Voor het activeren van het zoekendpoint: een Elasticsearch met API key en index(optioneel).

![img](../assets/Instellingen_voor_opslag.png)
Binary file added docs/developers/docker_desktop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 19 additions & 2 deletions docs/developers/installatie-van-nextcloud-demo-test-omgeving.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Volg deze eenvoudige stappen om de applicatie te starten:
3. **Code**: [Download](https://github.com/ConductionNL/opencatalogi/archive/refs/heads/master.zip) de code als zip bestand en pak deze uit.

4. **(Optie 1, Start Docker via installer)**
* [Download](https://raw.githubusercontent.com/OpenCatalogi/.github/main/docs/assets/Start-docker.bat) het .bat bestand (rechter muisknop opslaan als, let op dat je het bestand opslaat als .bat)
* [Download](https://raw.githubusercontent.com/OpenCatalogi/.github/main/docs/assets/Start-docker.bat) het `.bat`-bestand. Dit doe je door de link op te slaan (rechter muisknop opslaan als, let op dat je het bestand opslaat als `.bat`)

* Plaats het bestand als `.bat` in dezelfde folder als de code.

* Klik met de rechtermuisknop op het bestand en selecteer uitvoeren
**(Optie 2, via command line interface)**

* Type het volgende commando in de command prompt en druk op Enter:
* Type het volgende commando in de Command prompt en druk op Enter:

`cd pad/naar/uitgepakte/map`

Expand All @@ -48,4 +48,21 @@ Volg deze eenvoudige stappen om de applicatie te starten:

6. **Login**: Voor de standaardinstallatie werkt dit met admin als log **en** admin wachtwoord

Je hebt nu een werkende Nextcloud-test en demo-omgeving. Om OpenCatalogi the activeren, volg dan [deze stappen](https://github.com/ConductionNL/opencatalogi/blob/master/docs/developers/de-opencatalogi-app-toevoegen-aan-nextcloud.md)

En dat is het! Volg deze stappen om de OpenCatalogi-app snel en soepel op te zetten.

## Deinstaleren

Het kan natuurlijk voorkomen dat je na een succesvolle demonstratie de toepassing wil deinstalleren, open daarvoor de docker desktop interface en

* Vink onder `containers` alle containers aan en druk op 'delete'
* Vink onder `images` alle images aan en druk op 'delete'
* Vink onder `volumes` alle volumes aan en druk op 'delete'
* Verwijder de folder met bestanden die in stap 3 van het installatie proces hebt aangemaakt

![alt text](docker_desktop.png)

## Bijwerken

Vanuit de demo installatie route is er nog geen optie beschickbaar voor het bijwerken van de applicatie, die zal je moeten deinstaleren en instaleren.
38 changes: 31 additions & 7 deletions lib/Controller/AttachmentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ public function index(ObjectService $objectService): JSONResponse
}
}



$filters['_schema'] = 'attachment';

$result = $objectService->findObjects(filters: $filters, config: $dbConfig);
Expand Down Expand Up @@ -144,15 +142,25 @@ public function show(string|int $id, ObjectService $objectService): JSONResponse
}


/**
* @NoAdminRequired
* @NoCSRFRequired
*/
/**
* @NoAdminRequired
* @NoCSRFRequired
* @throws GuzzleException In case the file upload to NextCloud fails.
*/
public function create(ObjectService $objectService, ElasticSearchService $elasticSearchService): JSONResponse
{

$data = $this->request->getParams();

$uploadedFile = $this->request->getUploadedFile('_file');
// Todo: $uploadedFile['content'] does not contain the file content...
$this->fileService->uploadFile(content: $uploadedFile['content'], filePath: $uploadedFile['name']);
$data['downloadUrl'] = $this->fileService->createShareLink(path: $uploadedFile['name']);
$data['type'] = $uploadedFile['type'];
$data['size'] = $uploadedFile['size'];
$explodedName = explode('.', $uploadedFile['name']);
$data['title'] = $explodedName[0];
$data['extension'] = end($explodedName);

foreach($data as $key => $value) {
if(str_starts_with($key, '_')) {
unset($data[$key]);
Expand Down Expand Up @@ -188,6 +196,16 @@ public function update(string|int $id, ObjectService $objectService, ElasticSear
{
$data = $this->request->getParams();

$uploadedFile = $this->request->getUploadedFile('_file');
// Todo: $uploadedFile['content'] does not contain the file content...
$this->fileService->uploadFile(content: $uploadedFile['content'], filePath: $uploadedFile['name'], update: true);
// $data['downloadUrl'] = $this->fileService->createShareLink(path: $uploadedFile['name']);
$data['type'] = $uploadedFile['type'];
$data['size'] = $uploadedFile['size'];
$explodedName = explode('.', $uploadedFile['name']);
$data['title'] = $explodedName[0];
$data['extension'] = end($explodedName);

foreach($data as $key => $value) {
if(str_starts_with($key, '_')) {
unset($data[$key]);
Expand Down Expand Up @@ -223,9 +241,15 @@ public function update(string|int $id, ObjectService $objectService, ElasticSear
/**
* @NoAdminRequired
* @NoCSRFRequired
* @throws GuzzleException In case deleting the file from NextCloud fails.
* @throws \OCP\DB\Exception In case deleting attachment from the NextCloud DB fails.
*/
public function destroy(string|int $id, ObjectService $objectService, ElasticSearchService $elasticSearchService): JSONResponse
{
$attachment = $this->show($id, $objectService)->getData()->jsonSerialize();
// Todo: are we sure this is the best way to do this (how do we save the full path to this file in nextCloud)
$this->fileService->deleteFile(filePath: $attachment['title']. '.' .$attachment['extension']);

if($this->config->hasKey($this->appName, 'mongoStorage') === false
|| $this->config->getValueString($this->appName, 'mongoStorage') !== '1'
) {
Expand Down
103 changes: 93 additions & 10 deletions lib/Service/FileService.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,29 @@ private function getCurrentDomain(): string
return $protocol . $host;
}

/**
* Gets and returns an array with information about the current user.
* TODO: Username and password used for auth are currently set in config, this should (/could) be dynamic.
*
* @return array An array containing 'username', 'password' for auth and the 'currentUsername'.
*/
private function getUserInfo(): array
{
// Get the current user
$currentUser = $this->userSession->getUser();

return [
'username' => $this->config->getValueString(app: $this->appName, key: 'adminUsername', default: 'admin'),
'password' => $this->config->getValueString(app: $this->appName, key: 'adminPassword', default: 'admin'),
'currentUsername' => $currentUser ? $currentUser->getUID() : 'Guest'
];
}

/**
* Creates and returns a share link for a file (or folder).
* (https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#create-a-new-share)
*
* @param string $path Path to the file/folder which should be shared.
* @param string $path Path (from root) to the file/folder which should be shared.
* @param int|null $shareType 0 = user; 1 = group; 3 = public link; 4 = email; 6 = federated cloud share; 7 = circle; 10 = Talk conversation
* @param int|null $permissions 1 = read; 2 = update; 4 = create; 8 = delete; 16 = share; 31 = all (default: 31, for public shares: 1)
*
Expand All @@ -67,17 +85,12 @@ public function createShareLink(string $path, ?int $shareType = 3, ?int $permiss
// API endpoint to create a share
$url = "{$this->getCurrentDomain()}/ocs/v2.php/apps/files_sharing/api/v1/shares";

// Get the admin username & password for auth
$username = $this->config->getValueString(app: $this->appName, key: 'adminUsername', default: 'admin');
$password = $this->config->getValueString(app: $this->appName, key: 'adminPassword', default: 'admin');

// Get the current username
$currentUser = $this->userSession->getUser();
$currentUsername = $currentUser ? $currentUser->getUID() : 'Guest';
// Get the admin username & password for auth & get the current username
$userInfo = $this->getUserInfo();

// Data for the POST request
$options = [
'auth' => [$username, $password],
'auth' => [$userInfo['username'], $userInfo['password']],
'headers' => [
'OCS-APIREQUEST' => 'true',
'Content-Type' => 'application/x-www-form-urlencoded'
Expand All @@ -86,7 +99,7 @@ public function createShareLink(string $path, ?int $shareType = 3, ?int $permiss
'path' => $path,
'shareType' => $shareType,
'permissions' => $permissions,
'shareWith' => $currentUsername
'shareWith' => $userInfo['currentUsername']
]
];

Expand All @@ -100,4 +113,74 @@ public function createShareLink(string $path, ?int $shareType = 3, ?int $permiss
}
}

/**
* Uploads a file to nextCloud. Will overwrite a file if it already exists and create a new one if it doesn't exist.
*
* @param mixed $content The content of the file.
* @param string|null $filePath Path (from root) where to save the file. NOTE: this should include the name and extension/format of the file as well! (example.pdf)
* @param bool|null $update If set to true, the response status code 204 will also be seen as a success result. (NextCloud will return 204 when successfully updating a file)
*
* @return bool True if successful.
* @throws GuzzleException In case the Guzzle call returns an exception.
*/
public function uploadFile(mixed $content, ?string $filePath = '', ?bool $update = false): bool
{
// Get the admin username & password for auth & get the current username
$userInfo = $this->getUserInfo();

// API endpoint to upload the file
$url = $this->getCurrentDomain() . '/remote.php/dav/files/'
. $userInfo['currentUsername'] . '/' . ltrim(string: $filePath, characters: '/');

try {
$response = $this->client->request('PUT', $url, [
'auth' => [$userInfo['username'], $userInfo['password']],
'body' => $content
]);

if ($response->getStatusCode() === 201 || ($update === true && $response->getStatusCode() === 204)) {
return true;
}
} catch (\Exception $e) {
$str = $update === true ? 'update' : 'upload';
$this->logger->error("File $str failed: " . $e->getMessage());
throw $e;
}

return false;
}
Comment on lines +126 to +151
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waarom buitenom via de API als er een interne route voor bestaat?


/**
* Deletes a file from nextCloud.
*
* @param string $filePath Path (from root) to the file you want to delete.
*
* @return bool True if successful.
* @throws GuzzleException|Exception In case the Guzzle call returns an exception.
*/
public function deleteFile(string $filePath): bool
{
// Get the admin username & password for auth & get the current username
$userInfo = $this->getUserInfo();

// API endpoint to upload the file
$url = $this->getCurrentDomain() . '/remote.php/dav/files/'
. $userInfo['currentUsername'] . '/' . ltrim(string: $filePath, characters: '/');

try {
$response = $this->client->request('DELETE', $url, [
'auth' => [$userInfo['username'], $userInfo['password']],
]);

if ($response->getStatusCode() === 204) {
return true;
}
} catch (\Exception $e) {
$this->logger->error('File deletion failed: ' . $e->getMessage());
throw $e;
}

return false;
}
Comment on lines +161 to +184
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem, waarom buitenom als er een interne route voor is?


}
Loading
Loading