Move to OCS API

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2020-08-11 09:53:45 +02:00
parent 73df98c226
commit fea32748e6
No known key found for this signature in database
GPG key ID: 60C25B8C072916CF
13 changed files with 194 additions and 118 deletions

View file

@ -35,7 +35,8 @@ return [
['name' => 'page#index', 'url' => '/{hash}/results', 'verb' => 'GET', 'postfix' => 'results'], ['name' => 'page#index', 'url' => '/{hash}/results', 'verb' => 'GET', 'postfix' => 'results'],
['name' => 'page#goto_form', 'url' => '/{hash}', 'verb' => 'GET'], ['name' => 'page#goto_form', 'url' => '/{hash}', 'verb' => 'GET'],
],
'ocs' => [
// Forms // Forms
['name' => 'api#getForms', 'url' => '/api/v1/forms', 'verb' => 'GET'], ['name' => 'api#getForms', 'url' => '/api/v1/forms', 'verb' => 'GET'],
['name' => 'api#newForm', 'url' => '/api/v1/form', 'verb' => 'POST'], ['name' => 'api#newForm', 'url' => '/api/v1/form', 'verb' => 'POST'],

View file

@ -42,7 +42,9 @@ use OCA\Forms\Service\FormsService;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\IMapperException; use OCP\AppFramework\Db\IMapperException;
use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
use OCP\IRequest; use OCP\IRequest;
@ -84,6 +86,9 @@ class ApiController extends Controller {
/** @var FormsService */ /** @var FormsService */
private $formsService; private $formsService;
/** @var ISecureRandom */
private $secureRandom;
public function __construct(string $appName, public function __construct(string $appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
@ -95,7 +100,8 @@ class ApiController extends Controller {
OptionMapper $optionMapper, OptionMapper $optionMapper,
ILogger $logger, ILogger $logger,
IL10N $l10n, IL10N $l10n,
FormsService $formsService) { FormsService $formsService,
ISecureRandom $secureRandom) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->appName = $appName; $this->appName = $appName;
$this->userManager = $userManager; $this->userManager = $userManager;
@ -109,6 +115,7 @@ class ApiController extends Controller {
$this->logger = $logger; $this->logger = $logger;
$this->l10n = $l10n; $this->l10n = $l10n;
$this->formsService = $formsService; $this->formsService = $formsService;
$this->secureRandom = $secureRandom;
$this->currentUser = $userSession->getUser(); $this->currentUser = $userSession->getUser();
} }
@ -118,7 +125,7 @@ class ApiController extends Controller {
* *
* Read Form-List only with necessary information for Listing. * Read Form-List only with necessary information for Listing.
*/ */
public function getForms(): Http\JSONResponse { public function getForms(): DataResponse {
$forms = $this->formMapper->findAllByOwnerId($this->currentUser->getUID()); $forms = $this->formMapper->findAllByOwnerId($this->currentUser->getUID());
$result = []; $result = [];
@ -132,44 +139,51 @@ class ApiController extends Controller {
]; ];
} }
return new Http\JSONResponse($result); return new DataResponse($result);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
* *
*
* Read all information to edit a Form (form, questions, options, except submissions/answers). * Read all information to edit a Form (form, questions, options, except submissions/answers).
*
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function getForm(int $id): Http\JSONResponse { public function getForm(int $id): DataResponse {
try { try {
$form = $this->formsService->getForm($id); $form = $this->formsService->getForm($id);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if (!$this->formsService->hasUserAccess($id)) { if (!$this->formsService->hasUserAccess($id)) {
$this->logger->debug('User has no permissions to get this form'); $this->logger->debug('User has no permissions to get this form');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
return new Http\JSONResponse($form); return new DataResponse($form);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Create a new Form and return the Form to edit. * Create a new Form and return the Form to edit.
*
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function newForm(): Http\JSONResponse { public function newForm(): DataResponse {
$form = new Form(); $form = new Form();
$form->setOwnerId($this->currentUser->getUID()); $form->setOwnerId($this->currentUser->getUID());
$form->setCreated(time()); $form->setCreated(time());
$form->setHash(\OC::$server->getSecureRandom()->generate( $form->setHash($this->secureRandom->generate(
16, 16,
ISecureRandom::CHAR_HUMAN_READABLE ISecureRandom::CHAR_HUMAN_READABLE
)); ));
$form->setTitle(''); $form->setTitle('');
$form->setDescription(''); $form->setDescription('');
$form->setAccess([ $form->setAccess([
@ -183,7 +197,7 @@ class ApiController extends Controller {
$result = $form->read(); $result = $form->read();
$result['questions'] = []; $result['questions'] = [];
return new Http\JSONResponse($result); return new DataResponse($result);
} }
/** /**
@ -193,8 +207,10 @@ class ApiController extends Controller {
* *
* @param int $id FormId of form to update * @param int $id FormId of form to update
* @param array $keyValuePairs Array of key=>value pairs to update. * @param array $keyValuePairs Array of key=>value pairs to update.
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function updateForm(int $id, array $keyValuePairs): Http\JSONResponse { public function updateForm(int $id, array $keyValuePairs): DataResponse {
$this->logger->debug('Updating form: FormId: {id}, values: {keyValuePairs}', [ $this->logger->debug('Updating form: FormId: {id}, values: {keyValuePairs}', [
'id' => $id, 'id' => $id,
'keyValuePairs' => $keyValuePairs 'keyValuePairs' => $keyValuePairs
@ -204,12 +220,12 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($id); $form = $this->formMapper->findById($id);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Make sure we only store id // Make sure we only store id
@ -224,7 +240,7 @@ class ApiController extends Controller {
} }
} catch (Exception $e) { } catch (Exception $e) {
$this->logger->debug('Malformed access'); $this->logger->debug('Malformed access');
return new Http\JSONResponse(['message' => 'Malformed access'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Malformed access');
} }
// Create FormEntity with given Params & Id. // Create FormEntity with given Params & Id.
@ -234,13 +250,19 @@ class ApiController extends Controller {
// Update changed Columns in Db. // Update changed Columns in Db.
$this->formMapper->update($form); $this->formMapper->update($form);
return new Http\JSONResponse($form->getId()); return new DataResponse($form->getId());
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Delete a form
*
* @param int $id the form id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function deleteForm(int $id): Http\JSONResponse { public function deleteForm(int $id): DataResponse {
$this->logger->debug('Delete Form: {id}', [ $this->logger->debug('Delete Form: {id}', [
'id' => $id, 'id' => $id,
]); ]);
@ -249,12 +271,12 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($id); $form = $this->formMapper->findById($id);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Delete Submissions(incl. Answers), Questions(incl. Options) and Form. // Delete Submissions(incl. Answers), Questions(incl. Options) and Form.
@ -262,13 +284,21 @@ class ApiController extends Controller {
$this->questionMapper->deleteByForm($id); $this->questionMapper->deleteByForm($id);
$this->formMapper->delete($form); $this->formMapper->delete($form);
return new Http\JSONResponse($id); return new DataResponse($id);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Add a new question
*
* @param int $formId the form id
* @param string $type the new question type
* @param string $text the new question title
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function newQuestion(int $formId, string $type, string $text): Http\JSONResponse { public function newQuestion(int $formId, string $type, string $text = ''): DataResponse {
$this->logger->debug('Adding new question: formId: {formId}, type: {type}, text: {text}', [ $this->logger->debug('Adding new question: formId: {formId}, type: {type}, text: {text}', [
'formId' => $formId, 'formId' => $formId,
'type' => $type, 'type' => $type,
@ -277,19 +307,19 @@ class ApiController extends Controller {
if (array_search($type, Question::TYPES) === false) { if (array_search($type, Question::TYPES) === false) {
$this->logger->debug('Invalid type'); $this->logger->debug('Invalid type');
return new Http\JSONResponse(['message' => 'Invalid type'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Invalid type');
} }
try { try {
$form = $this->formMapper->findById($formId); $form = $this->formMapper->findById($formId);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse(['message' => 'Could not find form'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Retrieve all active questions sorted by Order. Takes the order of the last array-element and adds one. // Retrieve all active questions sorted by Order. Takes the order of the last array-element and adds one.
@ -314,16 +344,20 @@ class ApiController extends Controller {
$response = $question->read(); $response = $question->read();
$response['options'] = []; $response['options'] = [];
return new Http\JSONResponse($response); return new DataResponse($response);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Updates the Order of all Questions of a Form. * Updates the Order of all Questions of a Form.
*
* @param int $formId Id of the form to reorder * @param int $formId Id of the form to reorder
* @param int[] $newOrder Array of Question-Ids in new order. * @param int[] $newOrder Array of Question-Ids in new order.
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function reorderQuestions(int $formId, array $newOrder): Http\JSONResponse { public function reorderQuestions(int $formId, array $newOrder): DataResponse {
$this->logger->debug('Reordering Questions on Form {formId} as Question-Ids {newOrder}', [ $this->logger->debug('Reordering Questions on Form {formId} as Question-Ids {newOrder}', [
'formId' => $formId, 'formId' => $formId,
'newOrder' => $newOrder 'newOrder' => $newOrder
@ -333,25 +367,25 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($formId); $form = $this->formMapper->findById($formId);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse(['message' => 'Could not find form'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Check if array contains duplicates // Check if array contains duplicates
if (array_unique($newOrder) !== $newOrder) { if (array_unique($newOrder) !== $newOrder) {
$this->logger->debug('The given Array contains duplicates'); $this->logger->debug('The given Array contains duplicates');
return new Http\JSONResponse(['message' => 'The given Array contains duplicates'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('The given Array contains duplicates');
} }
// Check if all questions are given in Array. // Check if all questions are given in Array.
$questions = $this->questionMapper->findByForm($formId); $questions = $this->questionMapper->findByForm($formId);
if (sizeof($questions) !== sizeof($newOrder)) { if (sizeof($questions) !== sizeof($newOrder)) {
$this->logger->debug('The length of the given array does not match the number of stored questions'); $this->logger->debug('The length of the given array does not match the number of stored questions');
return new Http\JSONResponse(['message' => 'The length of the given array does not match the number of stored questions'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('The length of the given array does not match the number of stored questions');
} }
$questions = []; // Clear Array of Entities $questions = []; // Clear Array of Entities
@ -365,7 +399,7 @@ class ApiController extends Controller {
$this->logger->debug('Could not find question. Id:{id}', [ $this->logger->debug('Could not find question. Id:{id}', [
'id' => $questionId 'id' => $questionId
]); ]);
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
// Abort if a question is not part of the Form. // Abort if a question is not part of the Form.
@ -373,7 +407,7 @@ class ApiController extends Controller {
$this->logger->debug('This Question is not part of the given Form: questionId: {questionId}', [ $this->logger->debug('This Question is not part of the given Form: questionId: {questionId}', [
'questionId' => $questionId 'questionId' => $questionId
]); ]);
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
// Abort if a question is already marked as deleted (order==0) // Abort if a question is already marked as deleted (order==0)
@ -382,7 +416,7 @@ class ApiController extends Controller {
$this->logger->debug('This Question has already been marked as deleted: Id: {id}', [ $this->logger->debug('This Question has already been marked as deleted: Id: {id}', [
'id' => $questions[$arrayKey]->getId() 'id' => $questions[$arrayKey]->getId()
]); ]);
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
// Only set order, if it changed. // Only set order, if it changed.
@ -401,17 +435,21 @@ class ApiController extends Controller {
]; ];
} }
return new Http\JSONResponse($response); return new DataResponse($response);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Writes the given key-value pairs into Database. * Writes the given key-value pairs into Database.
* Key 'order' should only be changed by reorderQuestions() and is not allowed here. * Key 'order' should only be changed by reorderQuestions() and is not allowed here.
*
* @param int $id QuestionId of question to update * @param int $id QuestionId of question to update
* @param array $keyValuePairs Array of key=>value pairs to update. * @param array $keyValuePairs Array of key=>value pairs to update.
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function updateQuestion(int $id, array $keyValuePairs): Http\JSONResponse { public function updateQuestion(int $id, array $keyValuePairs): DataResponse {
$this->logger->debug('Updating question: questionId: {id}, values: {keyValuePairs}', [ $this->logger->debug('Updating question: questionId: {id}, values: {keyValuePairs}', [
'id' => $id, 'id' => $id,
'keyValuePairs' => $keyValuePairs 'keyValuePairs' => $keyValuePairs
@ -422,17 +460,17 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($question->getFormId()); $form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form or question'); $this->logger->debug('Could not find form or question');
return new Http\JSONResponse(['message' => 'Could not find form or question'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Could not find form or question');
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
if (array_key_exists('order', $keyValuePairs)) { if (array_key_exists('order', $keyValuePairs)) {
$this->logger->debug('Key \'order\' is not allowed on updateQuestion. Please use reorderQuestions() to change order.'); $this->logger->debug('Key \'order\' is not allowed on updateQuestion. Please use reorderQuestions() to change order.');
return new Http\JSONResponse(['message' => 'Please use reorderQuestions() to change order'], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException('Please use reorderQuestions() to change order');
} }
// Create QuestionEntity with given Params & Id. // Create QuestionEntity with given Params & Id.
@ -442,13 +480,19 @@ class ApiController extends Controller {
// Update changed Columns in Db. // Update changed Columns in Db.
$this->questionMapper->update($question); $this->questionMapper->update($question);
return new Http\JSONResponse($question->getId()); return new DataResponse($question->getId());
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Delete a question
*
* @param int $id the question id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function deleteQuestion(int $id): Http\JSONResponse { public function deleteQuestion(int $id): DataResponse {
$this->logger->debug('Mark question as deleted: {id}', [ $this->logger->debug('Mark question as deleted: {id}', [
'id' => $id, 'id' => $id,
]); ]);
@ -458,12 +502,12 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($question->getFormId()); $form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form or question'); $this->logger->debug('Could not find form or question');
return new Http\JSONResponse(['message' => 'Could not find form or question'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Could not find form or question');
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Store Order of deleted Question // Store Order of deleted Question
@ -483,13 +527,20 @@ class ApiController extends Controller {
} }
} }
return new Http\JSONResponse($id); return new DataResponse($id);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Add a new option to a question
*
* @param int $questionId the question id
* @param string $text the new option text
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function newOption(int $questionId, string $text): Http\JSONResponse { public function newOption(int $questionId, string $text): DataResponse {
$this->logger->debug('Adding new option: questionId: {questionId}, text: {text}', [ $this->logger->debug('Adding new option: questionId: {questionId}, text: {text}', [
'questionId' => $questionId, 'questionId' => $questionId,
'text' => $text, 'text' => $text,
@ -500,12 +551,12 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($question->getFormId()); $form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form or question'); $this->logger->debug('Could not find form or question');
return new Http\JSONResponse(['message' => 'Could not find form or question'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Could not find form or question');
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
$option = new Option(); $option = new Option();
@ -515,19 +566,22 @@ class ApiController extends Controller {
$option = $this->optionMapper->insert($option); $option = $this->optionMapper->insert($option);
return new Http\JSONResponse([ return new DataResponse([
'id' => $option->getId() 'id' => $option->getId()
]); ]);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Writes the given key-value pairs into Database. * Writes the given key-value pairs into Database.
* *
* @param int $id OptionId of option to update * @param int $id OptionId of option to update
* @param array $keyValuePairs Array of key=>value pairs to update. * @param array $keyValuePairs Array of key=>value pairs to update.
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function updateOption(int $id, array $keyValuePairs): Http\JSONResponse { public function updateOption(int $id, array $keyValuePairs): DataResponse {
$this->logger->debug('Updating option: option: {id}, values: {keyValuePairs}', [ $this->logger->debug('Updating option: option: {id}, values: {keyValuePairs}', [
'id' => $id, 'id' => $id,
'keyValuePairs' => $keyValuePairs 'keyValuePairs' => $keyValuePairs
@ -539,12 +593,12 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($question->getFormId()); $form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find option, question or form'); $this->logger->debug('Could not find option, question or form');
return new Http\JSONResponse(['message' => 'Could not find option, question or form'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Could not find option, question or form');
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Create OptionEntity with given Params & Id. // Create OptionEntity with given Params & Id.
@ -554,13 +608,19 @@ class ApiController extends Controller {
// Update changed Columns in Db. // Update changed Columns in Db.
$this->optionMapper->update($option); $this->optionMapper->update($option);
return new Http\JSONResponse($option->getId()); return new DataResponse($option->getId());
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Delete an option
*
* @param int $id the option id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function deleteOption(int $id): Http\JSONResponse { public function deleteOption(int $id): DataResponse {
$this->logger->debug('Deleting option: {id}', [ $this->logger->debug('Deleting option: {id}', [
'id' => $id 'id' => $id
]); ]);
@ -571,21 +631,27 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($question->getFormId()); $form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form or option'); $this->logger->debug('Could not find form or option');
return new Http\JSONResponse(['message' => 'Could not find form or option'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException('Could not find form or option');
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
$this->optionMapper->delete($option); $this->optionMapper->delete($option);
return new Http\JSONResponse($id); return new DataResponse($id);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Get all the answers of a given submission
*
* @param int $submissionId the submission id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
private function getAnswers(int $submissionId): array { private function getAnswers(int $submissionId): array {
try { try {
@ -605,24 +671,30 @@ class ApiController extends Controller {
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Get all the submissions of a given form
*
* @param string $hash the form hash
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function getSubmissions(string $hash): Http\JSONResponse { public function getSubmissions(string $hash): DataResponse {
try { try {
$form = $this->formMapper->findByHash($hash); $form = $this->formMapper->findByHash($hash);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse(['message' => 'Could not find form'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
try { try {
$submissionEntities = $this->submissionMapper->findByForm($form->getId()); $submissionEntities = $this->submissionMapper->findByForm($form->getId());
} catch (DoesNotExistException $e) { } catch (DoesNotExistException $e) {
//Just ignore, if no Data. Returns empty Submissions-Array // Just ignore, if no Data. Returns empty Submissions-Array
} }
$submissions = []; $submissions = [];
@ -658,7 +730,7 @@ class ApiController extends Controller {
'questions' => $questions, 'questions' => $questions,
]; ];
return new Http\JSONResponse($response); return new DataResponse($response);
} }
/** /**
@ -666,10 +738,13 @@ class ApiController extends Controller {
* @PublicPage * @PublicPage
* *
* Process a new submission * Process a new submission
* @param int $formId *
* @param int $formId the form id
* @param array $answers [question_id => arrayOfString] * @param array $answers [question_id => arrayOfString]
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function insertSubmission(int $formId, array $answers): Http\JSONResponse { public function insertSubmission(int $formId, array $answers): DataResponse {
$this->logger->debug('Inserting submission: formId: {formId}, answers: {answers}', [ $this->logger->debug('Inserting submission: formId: {formId}, answers: {answers}', [
'formId' => $formId, 'formId' => $formId,
'answers' => $answers, 'answers' => $answers,
@ -680,22 +755,22 @@ class ApiController extends Controller {
$questions = $this->formsService->getQuestions($formId); $questions = $this->formsService->getQuestions($formId);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse(['message' => 'Could not find form'], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
// Does the user have access to the form // Does the user have access to the form
if (!$this->formsService->hasUserAccess($form->getId())) { if (!$this->formsService->hasUserAccess($form->getId())) {
return new Http\JSONResponse(['message' => 'Not allowed to access this form'], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException('Not allowed to access this form');
} }
// Not allowed if form expired. Expires is '0' if the form does not expire. // Not allowed if form expired. Expires is '0' if the form does not expire.
if ($form->getExpires() && $form->getExpires() < time()) { if ($form->getExpires() && $form->getExpires() < time()) {
return new Http\JSONResponse(['message' => 'This form is no longer taking answers'], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException('This form is no longer taking answers');
} }
// Does the user have permissions to submit // Does the user have permissions to submit
if (!$this->formsService->canSubmit($form->getId())) { if (!$this->formsService->canSubmit($form->getId())) {
return new Http\JSONResponse(['message' => 'Already submitted'], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException('Already submitted');
} }
// Create Submission // Create Submission
@ -753,13 +828,19 @@ class ApiController extends Controller {
} }
} }
return new Http\JSONResponse([]); return new DataResponse();
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Delete a specific submission
*
* @param int $id the submission id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function deleteSubmission(int $id): Http\JSONResponse { public function deleteSubmission(int $id): DataResponse {
$this->logger->debug('Delete Submission: {id}', [ $this->logger->debug('Delete Submission: {id}', [
'id' => $id, 'id' => $id,
]); ]);
@ -769,24 +850,30 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($submission->getFormId()); $form = $this->formMapper->findById($submission->getFormId());
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form or submission'); $this->logger->debug('Could not find form or submission');
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Delete submission (incl. Answers) // Delete submission (incl. Answers)
$this->submissionMapper->delete($submission); $this->submissionMapper->delete($submission);
return new Http\JSONResponse($id); return new DataResponse($id);
} }
/** /**
* @NoAdminRequired * @NoAdminRequired
*
* Delete all submissions of a specified form
*
* @param int $formId the form id
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/ */
public function deleteAllSubmissions(int $formId): Http\JSONResponse { public function deleteAllSubmissions(int $formId): DataResponse {
$this->logger->debug('Delete all submissions to form: {formId}', [ $this->logger->debug('Delete all submissions to form: {formId}', [
'formId' => $formId, 'formId' => $formId,
]); ]);
@ -795,17 +882,17 @@ class ApiController extends Controller {
$form = $this->formMapper->findById($formId); $form = $this->formMapper->findById($formId);
} catch (IMapperException $e) { } catch (IMapperException $e) {
$this->logger->debug('Could not find form'); $this->logger->debug('Could not find form');
return new Http\JSONResponse([], Http::STATUS_BAD_REQUEST); throw new OCSBadRequestException();
} }
if ($form->getOwnerId() !== $this->currentUser->getUID()) { if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user'); $this->logger->debug('This form is not owned by the current user');
return new Http\JSONResponse([], Http::STATUS_FORBIDDEN); throw new OCSForbiddenException();
} }
// Delete all submissions (incl. Answers) // Delete all submissions (incl. Answers)
$this->submissionMapper->deleteByForm($formId); $this->submissionMapper->deleteByForm($formId);
return new Http\JSONResponse($formId); return new DataResponse($formId);
} }
} }

View file

@ -71,7 +71,7 @@
<script> <script>
import { emit } from '@nextcloud/event-bus' import { emit } from '@nextcloud/event-bus'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import AppContent from '@nextcloud/vue/dist/Components/AppContent' import AppContent from '@nextcloud/vue/dist/Components/AppContent'
@ -146,7 +146,7 @@ export default {
async loadForms() { async loadForms() {
this.loading = true this.loading = true
try { try {
const response = await axios.get(generateUrl('apps/forms/api/v1/forms')) const response = await axios.get(generateOcsUrl('apps/forms/api/v1', 2) + 'forms')
this.forms = response.data this.forms = response.data
} catch (error) { } catch (error) {
showError(t('forms', 'An error occurred while loading the forms list')) showError(t('forms', 'An error occurred while loading the forms list'))
@ -162,7 +162,7 @@ export default {
async onNewForm() { async onNewForm() {
try { try {
// Request a new empty form // Request a new empty form
const response = await axios.post(generateUrl('/apps/forms/api/v1/form')) const response = await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'form')
const newForm = response.data const newForm = response.data
this.forms.unshift(newForm) this.forms.unshift(newForm)
this.$router.push({ name: 'edit', params: { hash: newForm.hash } }) this.$router.push({ name: 'edit', params: { hash: newForm.hash } })

View file

@ -57,7 +57,7 @@
</template> </template>
<script> <script>
import { generateUrl } from '@nextcloud/router' import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import ActionLink from '@nextcloud/vue/dist/Components/ActionLink' import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
@ -174,7 +174,7 @@ export default {
// All good, let's delete // All good, let's delete
this.loading = true this.loading = true
try { try {
await axios.delete(generateUrl('/apps/forms/api/v1/form/{id}', { id: this.form.id })) await axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `form/${this.form.id}`)
this.$emit('delete', this.form.id) this.$emit('delete', this.form.id)
} catch (error) { } catch (error) {
showError(t('forms', 'Error while deleting {title}', { title: this.formTitle })) showError(t('forms', 'Error while deleting {title}', { title: this.formTitle }))

View file

@ -29,7 +29,7 @@
<script> <script>
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import pDebounce from 'p-debounce' import pDebounce from 'p-debounce'
import PQueue from 'p-queue' import PQueue from 'p-queue'
@ -143,7 +143,7 @@ export default {
*/ */
async createAnswer(answer) { async createAnswer(answer) {
try { try {
const response = await axios.post(generateUrl('/apps/forms/api/v1/option'), { const response = await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'option', {
questionId: answer.question_id, questionId: answer.question_id,
text: answer.text, text: answer.text,
}) })
@ -171,7 +171,7 @@ export default {
*/ */
async updateAnswer(answer) { async updateAnswer(answer) {
try { try {
await axios.post(generateUrl('/apps/forms/api/v1/option/update'), { await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'option/update', {
id: this.answer.id, id: this.answer.id,
keyValuePairs: { keyValuePairs: {
text: answer.text, text: answer.text,

View file

@ -83,7 +83,7 @@
</template> </template>
<script> <script>
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
@ -305,7 +305,7 @@ export default {
if (!option.local) { if (!option.local) {
// let's not await, deleting in background // let's not await, deleting in background
axios.delete(generateUrl('/apps/forms/api/v1/option/{id}', { id: option.id })) axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `option/${option.id}`)
.catch(error => { .catch(error => {
showError(t('forms', 'There was an issue deleting this option')) showError(t('forms', 'There was an issue deleting this option'))
console.error(error) console.error(error)

View file

@ -90,7 +90,7 @@
</template> </template>
<script> <script>
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
@ -312,7 +312,7 @@ export default {
if (!option.local) { if (!option.local) {
// let's not await, deleting in background // let's not await, deleting in background
axios.delete(generateUrl('/apps/forms/api/v1/option/{id}', { id: option.id })) axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `option/${option.id}`)
.catch(error => { .catch(error => {
showError(t('forms', 'There was an issue deleting this option')) showError(t('forms', 'There was an issue deleting this option'))
console.error(error) console.error(error)

View file

@ -209,7 +209,7 @@ export default {
this.SHARE_TYPES.SHARE_TYPE_GROUP, this.SHARE_TYPES.SHARE_TYPE_GROUP,
] ]
const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1') + 'sharees', { const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1', 2) + 'sharees', {
params: { params: {
format: 'json', format: 'json',
itemType: 'file', itemType: 'file',
@ -219,11 +219,6 @@ export default {
}, },
}) })
if (request.data.ocs.meta.statuscode !== 100) {
console.error('Error fetching suggestions', request)
return
}
const data = request.data.ocs.data const data = request.data.ocs.data
const exact = request.data.ocs.data.exact const exact = request.data.ocs.data.exact
data.exact = [] // removing exact from general results data.exact = [] // removing exact from general results
@ -263,18 +258,13 @@ export default {
async getRecommendations() { async getRecommendations() {
this.loading = true this.loading = true
const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1') + 'sharees_recommended', { const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1', 2) + 'sharees_recommended', {
params: { params: {
format: 'json', format: 'json',
itemType: 'file', itemType: 'file',
}, },
}) })
if (request.data.ocs.meta.statuscode !== 100) {
console.error('Error fetching recommendations', request)
return
}
const exact = request.data.ocs.data.exact const exact = request.data.ocs.data.exact
// flatten array of arrays // flatten array of arrays

View file

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { debounce } from 'debounce' import { debounce } from 'debounce'
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
@ -170,7 +170,7 @@ export default {
async saveQuestionProperty(key, value) { async saveQuestionProperty(key, value) {
try { try {
// TODO: add loading status feedback ? // TODO: add loading status feedback ?
await axios.post(generateUrl('/apps/forms/api/v1/question/update'), { await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'question/update', {
id: this.id, id: this.id,
keyValuePairs: { keyValuePairs: {
[key]: value, [key]: value,

View file

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
@ -39,7 +39,7 @@ export default {
async saveFormProperty(key) { async saveFormProperty(key) {
try { try {
// TODO: add loading status feedback ? // TODO: add loading status feedback ?
await axios.post(generateUrl('/apps/forms/api/v1/form/update'), { await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'form/update', {
id: this.form.id, id: this.form.id,
keyValuePairs: { keyValuePairs: {
[key]: this.form[key], [key]: this.form[key],

View file

@ -121,7 +121,7 @@
<script> <script>
import { emit } from '@nextcloud/event-bus' import { emit } from '@nextcloud/event-bus'
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
@ -252,7 +252,7 @@ export default {
this.cancelFetchFullForm = cancel this.cancelFetchFullForm = cancel
try { try {
const form = await request(generateUrl('/apps/forms/api/v1/form/{id}', { id })) const form = await request(generateOcsUrl('apps/forms/api/v1', 2) + `form/${id}`)
this.$emit('update:form', form.data) this.$emit('update:form', form.data)
this.isLoadingForm = false this.isLoadingForm = false
} catch (error) { } catch (error) {
@ -299,7 +299,7 @@ export default {
this.isLoadingQuestions = true this.isLoadingQuestions = true
try { try {
const response = await axios.post(generateUrl('/apps/forms/api/v1/question'), { const response = await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'question', {
formId: this.form.id, formId: this.form.id,
type, type,
text, text,
@ -337,7 +337,7 @@ export default {
this.isLoadingQuestions = true this.isLoadingQuestions = true
try { try {
await axios.delete(generateUrl('/apps/forms/api/v1/question/{id}', { id })) await axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `question/${id}`)
const index = this.form.questions.findIndex(search => search.id === id) const index = this.form.questions.findIndex(search => search.id === id)
this.form.questions.splice(index, 1) this.form.questions.splice(index, 1)
} catch (error) { } catch (error) {
@ -356,7 +356,7 @@ export default {
const newOrder = this.form.questions.map(question => question.id) const newOrder = this.form.questions.map(question => question.id)
try { try {
await axios.post(generateUrl('/apps/forms/api/v1/question/reorder'), { await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'question/reorder', {
formId: this.form.id, formId: this.form.id,
newOrder, newOrder,
}) })

View file

@ -117,7 +117,7 @@
</template> </template>
<script> <script>
import { generateUrl } from '@nextcloud/router' import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import { Parser } from 'json2csv' import { Parser } from 'json2csv'
import { showError, showSuccess } from '@nextcloud/dialogs' import { showError, showSuccess } from '@nextcloud/dialogs'
import Actions from '@nextcloud/vue/dist/Components/Actions' import Actions from '@nextcloud/vue/dist/Components/Actions'
@ -214,9 +214,7 @@ export default {
console.debug('Loading results for form', this.form.hash) console.debug('Loading results for form', this.form.hash)
try { try {
const response = await axios.get(generateUrl('/apps/forms/api/v1/submissions/{hash}', { const response = await axios.get(generateOcsUrl('apps/forms/api/v1', 2) + `submissions/${this.form.hash}`)
hash: this.form.hash,
}))
// Append questions & submissions // Append questions & submissions
this.$set(this.form, 'submissions', response.data.submissions) this.$set(this.form, 'submissions', response.data.submissions)
@ -233,7 +231,7 @@ export default {
this.loadingResults = true this.loadingResults = true
try { try {
await axios.delete(generateUrl('/apps/forms/api/v1/submission/{id}', { id })) await axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `submission/${id}`)
const index = this.form.submissions.findIndex(search => search.id === id) const index = this.form.submissions.findIndex(search => search.id === id)
this.form.submissions.splice(index, 1) this.form.submissions.splice(index, 1)
} catch (error) { } catch (error) {
@ -251,7 +249,7 @@ export default {
this.loadingResults = true this.loadingResults = true
try { try {
await axios.delete(generateUrl('/apps/forms/api/v1/submissions/{formId}', { formId: this.form.id })) await axios.delete(generateOcsUrl('apps/forms/api/v1', 2) + `submissions/${this.form.id}`)
this.form.submissions = [] this.form.submissions = []
} catch (error) { } catch (error) {
console.error(error) console.error(error)

View file

@ -77,7 +77,7 @@
<script> <script>
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import { generateUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import AppContent from '@nextcloud/vue/dist/Components/AppContent' import AppContent from '@nextcloud/vue/dist/Components/AppContent'
@ -188,7 +188,7 @@ export default {
this.loading = true this.loading = true
try { try {
await axios.post(generateUrl('/apps/forms/api/v1/submission/insert'), { await axios.post(generateOcsUrl('apps/forms/api/v1', 2) + 'submission/insert', {
formId: this.form.id, formId: this.form.id,
answers: this.answers, answers: this.answers,
}) })