Skip to content

Commit

Permalink
Code review changes
Browse files Browse the repository at this point in the history
Signed-off-by: Konstantin Myakshin <[email protected]>
  • Loading branch information
Koc committed Nov 17, 2023
1 parent 42656a5 commit 3b49922
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 38 deletions.
6 changes: 3 additions & 3 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
'url' => '/api/{apiVersion}/submissions/link/{fileFormat}',
'verb' => 'POST',
'requirements' => [
'apiVersion' => 'v2(\.1)?',
'apiVersion' => 'v2(\.2)?',
'fileFormat' => 'csv|ods|xlsx'
]
],
Expand All @@ -242,15 +242,15 @@
'url' => '/api/{apiVersion}/submissions/linkedFile/{hash}',
'verb' => 'GET',
'requirements' => [
'apiVersion' => 'v2(\.1)?'
'apiVersion' => 'v2(\.2)?'
]
],
[
'name' => 'api#unlinkFile',
'url' => '/api/{apiVersion}/submissions/unlink',
'verb' => 'POST',
'requirements' => [
'apiVersion' => 'v2(\.1)?'
'apiVersion' => 'v2(\.2)?'
]
],
// Submissions
Expand Down
70 changes: 59 additions & 11 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ This file contains the API-Documentation. For more information on the returned D
- Completely new way of handling access & shares.

### Other API changes
- In API version 2.2 next endpoints were introduced:
- `POST /api/2.2/submissions/link/{fileFormat}` to link form to a file
- `GET /api/2.2/submissions/linkedFile/{hash}` to retrieve linked file
- `POST /api/2.2/submissions/unlink` to unlink form from a file
- In API version 2.2 next endpoints were changed:
- `GET /api/v2.1/submissions/export/{hash}` was extended with optional parameter `fileFormat` to export submissions in different formats
- `GET /api/v2.1/submissions/export` was extended with optional parameter `fileFormat` to export submissions to cloud in different formats
- In API version 2.1 the endpoint `/api/v2.1/share/update` was added to update a Share

## Form Endpoints
Expand Down Expand Up @@ -230,6 +237,45 @@ Update a single or multiple properties of a form-object. Concerns **only** the F
"data": 3
```

### Link a form to a file
- Endpoint: `/api/v2.2/submissions/link/{fileFormat}`
- Url-Parameter:
| Parameter | Type | Description |
|--------------|---------|--------------|
| _fileFormat_ | String | csv|ods|xlsx |
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
|-----------|---------|--------------------------------------------|
| _hash_ | String | Hash of the form to update |
| _path_ | String | Path within User-Dir, to store the file to |
- Response: **Status-Code OK**, as well as the linked file name.

### Get linked file
- Endpoint: `/api/v2.2/submissions/linkedFile/{hash}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|------------------|
| _hash_ | String | Hash of the form |
- Method: `GET`
- Response:
```
"data": {
"fileId": 157,
"path": "foo/bar"
"fileFormat": "csv"
}
```

### Unlink file from form
- Endpoint: `/api/v2.2/submissions/unlink`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
|-----------|---------|----------------------------|
| _hash_ | String | Hash of the form to update |
- Response: **Status-Code OK**

## Question Endpoints
Contains only manipulative question-endpoints. To retrieve questions, request the full form data.

Expand All @@ -242,7 +288,7 @@ Contains only manipulative question-endpoints. To retrieve questions, request th
| _formId_ | Integer | | ID of the form, the new question will belong to |
| _type_ | [QuestionType](DataStructure.md#question-types) | | The question-type of the new question |
| _text_ | String | yes | *Optional* The text of the new question. |
- Response: The new question object.
- Response: The new question object.
```
"data": {
"id": 3,
Expand Down Expand Up @@ -397,7 +443,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the
|------------------|----------|-------------|
| _id_ | Integer | ID of the share to update |
| *keyValuePairs*¹ | Array | Array of key-value pairs to update |

¹Currently only the _permissions_ can be updated.
- Method: `POST`
- Response: **Status-Code OK**, as well as the id of the share object.
Expand Down Expand Up @@ -506,11 +552,12 @@ Get all Submissions to a Form
Returns all submissions to the form in form of a csv-file.
- Endpoint: `/api/v2.1/submissions/export/{hash}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
| _hash_ | String | Hash of the form to get the submissions for |
| Parameter | Type | Description |
|--------------|---------|-------------|
| _hash_ | String | Hash of the form to get the submissions for |
| _fileFormat_ | String | csv|ods|xlsx |
- Method: `GET`
- Response: A Data Download Response containg the headers `Content-Disposition: attachment; filename="Form 1 (responses).csv"` and `Content-Type: text/csv;charset=UTF-8`. The actual data contains all submissions to the referred form, formatted as comma separated and escaped csv.
- Response: A Data Download Response contains the headers `Content-Disposition: attachment; filename="Form 1 (responses).csv"` and `Content-Type: text/csv;charset=UTF-8`. The actual data contains all submissions to the referred form, formatted as comma separated and escaped csv.
```
"User display name","Timestamp","Question 1","Question 2"
"jonas","Friday, January 22, 2021 at 12:47:29 AM GMT+0:00","Option 2","Answer"
Expand All @@ -522,10 +569,11 @@ Creates a csv file and stores it to the cloud, resp. Files-App.
- Endpoint: `/api/v2.1/submissions/export`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
|-----------|---------|-------------|
| _hash_ | String | Hash of the form to get the submissions for |
| _path_ | String | Path within User-Dir, to store the file to |
| Parameter | Type | Description |
|--------------|---------|-------------|
| _hash_ | String | Hash of the form to get the submissions for |
| _path_ | String | Path within User-Dir, to store the file to |
| _fileFormat_ | String | csv|ods|xlsx |
- Response: Stores the file to the given path and returns the fileName.
```
"data": "Form 2 (responses).csv"
Expand Down Expand Up @@ -554,7 +602,7 @@ Store Submission to Database
| _formId_ | Integer | ID of the form to submit into |
| _answers_ | Array | Array of Answers |
| _shareHash_ | String | optional, only neccessary for submissions to a public share link |

The Array of Answers has the following structure:
- QuestionID as key
- An **array** of values as value --> Even for short Text Answers, wrapped into Array.
Expand Down
8 changes: 8 additions & 0 deletions lib/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,12 @@ class Constants {
* Constants related to extra settings for questions
*/
public const QUESTION_EXTRASETTINGS_OTHER_PREFIX = 'system-other-answer:';

public const SUPPORTED_EXPORT_FORMATS = [
'csv' => 'text/csv',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
];

public const DEFAULT_FILE_FORMAT = 'csv';
}
49 changes: 39 additions & 10 deletions lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@
use Psr\Log\LoggerInterface;

class ApiController extends OCSController {
private const DEFAULT_FILE_FORMAT = 'csv';

/** @var IUser */
private $currentUser;

Expand Down Expand Up @@ -992,7 +990,7 @@ public function insertSubmission(int $formId, array $answers, string $shareHash
$fileFormat = $form->getFileFormat();
$ownerId = $form->getOwnerId();

$this->submissionService->writeFileToCloud($hash, $filePath, $fileFormat, $ownerId);
$this->submissionService->writeFileToCloud($form, $filePath, $fileFormat, $ownerId);
}

return new DataResponse();
Expand Down Expand Up @@ -1083,7 +1081,7 @@ public function deleteAllSubmissions(int $formId): DataResponse {
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/
public function exportSubmissions(string $hash, string $fileFormat = self::DEFAULT_FILE_FORMAT): DataDownloadResponse {
public function exportSubmissions(string $hash, string $fileFormat = Constants::DEFAULT_FILE_FORMAT): DataDownloadResponse {
$this->logger->debug('Export submissions for form: {hash}', [
'hash' => $hash,
]);
Expand All @@ -1103,7 +1101,7 @@ public function exportSubmissions(string $hash, string $fileFormat = self::DEFAU
$submissionsData = $this->submissionService->getSubmissionsData($form, $fileFormat);
$fileName = $this->submissionService->getFileName($form, $fileFormat);

return new DataDownloadResponse($submissionsData, $fileName, SubmissionService::SUPPORTED_EXPORT_FORMATS[$fileFormat]);
return new DataDownloadResponse($submissionsData, $fileName, Constants::SUPPORTED_EXPORT_FORMATS[$fileFormat]);
}

/**
Expand All @@ -1119,7 +1117,7 @@ public function exportSubmissions(string $hash, string $fileFormat = self::DEFAU
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/
public function exportSubmissionsToCloud(string $hash, string $path, string $fileFormat = self::DEFAULT_FILE_FORMAT): DataResponse {
public function exportSubmissionsToCloud(string $hash, string $path, string $fileFormat = Constants::DEFAULT_FILE_FORMAT): DataResponse {
try {
$form = $this->formMapper->findByHash($hash);
} catch (IMapperException $e) {
Expand All @@ -1132,7 +1130,7 @@ public function exportSubmissionsToCloud(string $hash, string $path, string $fil
throw new OCSForbiddenException();
}

$file = $this->submissionService->writeFileToCloud($hash, $path, $fileFormat);
$file = $this->submissionService->writeFileToCloud($form, $path, $fileFormat);

return new DataResponse($file->getName());
}
Expand All @@ -1147,9 +1145,25 @@ public function exportSubmissionsToCloud(string $hash, string $path, string $fil
* @return DataResponse
*/
public function getLinkedFile(string $hash): DataResponse {
$form = $this->formMapper->findByHash($hash);
try {
$form = $this->formMapper->findByHash($hash);
} catch (IMapperException $e) {
$this->logger->debug('Could not find form');
throw new OCSNotFoundException();
}

if (!$this->formsService->canSeeResults($form)) {
$this->logger->debug('The current user has no permission to get the results for this form');
throw new OCSForbiddenException();
}

$filePath = $this->submissionService->getFilePath($form);

if (!$filePath) {
$this->logger->debug('Form not linked to file');
throw new OCSBadRequestException();
}

return new DataResponse([
'fileId' => $form->getFileId(),
'path' => $filePath,
Expand All @@ -1163,7 +1177,22 @@ public function getLinkedFile(string $hash): DataResponse {
* @param string $hash of the form
*/
public function unlinkFile(string $hash): DataResponse {
$form = $this->formMapper->findByHash($hash);
try {
$form = $this->formMapper->findByHash($hash);
} catch (IMapperException $e) {
$this->logger->debug('Could not find form');
throw new OCSNotFoundException();
}

if (!$this->formsService->canSeeResults($form)) {
$this->logger->debug('The current user has no permission to get the results for this form');
throw new OCSForbiddenException();
}

if (!$form->getFileId()) {
$this->logger->debug('Form not linked to file');
throw new OCSBadRequestException();
}

$form->setFileId(null);
$form->setFileFormat(null);
Expand Down Expand Up @@ -1203,7 +1232,7 @@ public function linkFile(string $hash, string $path, string $fileFormat): DataRe
throw new OCSForbiddenException();
}

$file = $this->submissionService->writeFileToCloud($hash, $path, $fileFormat);
$file = $this->submissionService->writeFileToCloud($form, $path, $fileFormat);

$form->setFileId($file->getId());
$form->setFileFormat($fileFormat);
Expand Down
19 changes: 6 additions & 13 deletions lib/Service/SubmissionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,6 @@
use Psr\Log\LoggerInterface;

class SubmissionService {
public const SUPPORTED_EXPORT_FORMATS = [
'csv' => 'text/csv',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
];

/** @var FormMapper */
private $formMapper;

Expand Down Expand Up @@ -164,25 +158,24 @@ public function getSubmissions(int $formId): array {
/**
* Export Submissions to Cloud-Filesystem
*
* @param string $hash of the form
* @param Form $form the form
* @param string $path The Cloud-Path to export to
* @param string $fileFormat Format to export to
* @param string $ownerId of the form creator
* @return File The written file
* @throws NotPermittedException
*/
public function writeFileToCloud(string $hash, string $path, string $fileFormat, ?string $ownerId = null): File {
if (empty(self::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
public function writeFileToCloud(Form $form, string $path, string $fileFormat, ?string $ownerId = null): File {
if (empty(Constants::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
throw new \InvalidArgumentException('Invalid file format');
}

$this->logger->debug('Export submissions for form: {hash} to Cloud at: /{path} in format {fileFormat}', [
'hash' => $hash,
'hash' => $form->getHash(),
'path' => $path,
'fileFormat' => $fileFormat,
]);

$form = $this->formMapper->findByHash($hash);
$fileName = $this->getFileName($form, $fileFormat);

/** @var \OCP\Files\Folder|File $node */
Expand Down Expand Up @@ -235,7 +228,7 @@ public function writeFileToCloud(string $hash, string $path, string $fileFormat,
* @return string File content
*/
public function getSubmissionsData(Form $form, string $fileFormat, ?File $file = null): string {
if (empty(self::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
if (empty(Constants::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
throw new \InvalidArgumentException('Invalid file format');
}

Expand Down Expand Up @@ -313,7 +306,7 @@ public function getSubmissionsData(Form $form, string $fileFormat, ?File $file =
}

public function getFileName(Form $form, string $fileFormat): string {
if (empty(self::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
if (empty(Constants::SUPPORTED_EXPORT_FORMATS[$fileFormat])) {
throw new \InvalidArgumentException('Invalid file format');
}

Expand Down
2 changes: 1 addition & 1 deletion src/views/Results.vue
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ import SetWindowTitle from '../utils/SetWindowTitle.js'
import OcsResponse2Data from '../utils/OcsResponse2Data.js'
import PermissionTypes from '../mixins/PermissionTypes.js'

const picker = getFilePickerBuilder(t('forms', 'Save to Files'))
const picker = getFilePickerBuilder(t('forms', 'Choose spreadsheet location'))
.setMultiSelect(false)
.setModal(true)
.setType(1)
Expand Down

0 comments on commit 3b49922

Please sign in to comment.