aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/JsonApi/Routes
diff options
context:
space:
mode:
Diffstat (limited to 'lib/classes/JsonApi/Routes')
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/Authority.php28
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsCreate.php106
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsDelete.php54
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsShow.php28
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardsCreate.php46
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardsDelete.php31
-rw-r--r--lib/classes/JsonApi/Routes/Clipboards/ClipboardsUpdate.php50
-rw-r--r--lib/classes/JsonApi/Routes/Consultations/SlotCreationCount.php105
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php14
-rw-r--r--lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php2
-rw-r--r--lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php11
-rw-r--r--lib/classes/JsonApi/Routes/Files/SubfoldersIndex.php23
12 files changed, 489 insertions, 9 deletions
diff --git a/lib/classes/JsonApi/Routes/Clipboards/Authority.php b/lib/classes/JsonApi/Routes/Clipboards/Authority.php
new file mode 100644
index 0000000..5cc053a
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/Authority.php
@@ -0,0 +1,28 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use User;
+
+final class Authority
+{
+ public static function canCreateClipboard(User $user): bool
+ {
+ return true;
+ }
+
+ public static function canAccessClipboard(User $user, \Clipboard $clipboard): bool
+ {
+ return $user->id === $clipboard->user_id
+ || $user->perms === 'root';
+ }
+
+ public static function canUpdateClipboard(User $user, \Clipboard $clipboard): bool
+ {
+ return self::canAccessClipboard($user, $clipboard);
+ }
+
+ public static function canDeleteClipboard(User $user, \Clipboard $clipboard): bool
+ {
+ return self::canUpdateClipboard($user, $clipboard);
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsCreate.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsCreate.php
new file mode 100644
index 0000000..d57d0c5
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsCreate.php
@@ -0,0 +1,106 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\JsonApiController;
+use JsonApi\Routes\ValidationTrait;
+use JsonApi\Schemas\Clipboard;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardItemsCreate extends JsonApiController
+{
+ use ValidationTrait;
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $json = $this->validate($request, $args);
+
+ $clipboard_id = $args['id'] ?? $json['data']['relationships']['clipboard']['data']['id'];
+ $clipboard = \Clipboard::find($clipboard_id);
+
+ $user = $this->getUser($request);
+ if (!Authority::canUpdateClipboard($user, $clipboard)) {
+ throw new AuthorizationFailedException();
+ }
+
+ $range_id = $json['data']['attributes']['range_id'];
+ $range_type = $json['data']['attributes']['range_type'];
+
+ $item = \ClipboardItem::findOneBySql(
+ 'clipboard_id = ? AND range_id = ? AND range_type = ?',
+ [$clipboard_id, $range_id, $range_type]
+ );
+
+ if ($item) {
+ return $this->getCodeResponse(302, [
+ 'Location' => $this->getLinkToItem($item),
+ ]);
+ }
+
+ $item = \ClipboardItem::create([
+ 'clipboard_id' => $clipboard_id,
+ 'range_id' => $range_id,
+ 'range_type' => $range_type,
+ ]);
+
+ return $this->getContentResponse($item);
+ }
+
+ protected function validateResourceDocument($json, $data)
+ {
+ $clipboardValidationError = $this->validateRequestContainsValidClipboard($json, $data);
+ if ($clipboardValidationError !== null) {
+ return $clipboardValidationError;
+ }
+
+ if (!self::arrayHas($json, 'data.attributes.range_id')) {
+ return 'No range_id defined';
+ }
+
+ if (!self::arrayHas($json, 'data.attributes.range_type')) {
+ return 'No range_type defined';
+ }
+
+ $range_type = self::arrayGet($json, 'data.attributes.range_type');
+ if (!is_a($range_type, \StudipItem::class, true)) {
+ return 'Range type must implement interface StudipItem';
+ }
+
+ return null;
+ }
+
+ private function validateRequestContainsValidClipboard($json, $data): ?string
+ {
+ if (isset($data['id'])) {
+ if (!\Clipboard::exists($data['id'])) {
+ return 'Provided clipboard id is invalid';
+ }
+ } else {
+ if (!self::arrayHas($json, 'data.relationships.clipboard')) {
+ return 'No clipboard relationship defined';
+ }
+
+ $clipboard = self::arrayGet($json, 'data.relationships.clipboard');
+ if (
+ !isset($clipboard['data']['type'], $clipboard['data']['id'])
+ || $clipboard['data']['type'] !== Clipboard::TYPE
+ ) {
+ return 'Defined clipboard relationship has invalid format.';
+ }
+ if (!\Clipboard::exists($clipboard['data']['id'])) {
+ return 'Related clipboard does not exist.';
+ }
+ }
+
+ return null;
+ }
+
+ private function getLinkToItem(\ClipboardItem $item): string
+ {
+ $json = $this->encoder->encodeData($item);
+ return json_decode($json, true)['data']['links']['self'];
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsDelete.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsDelete.php
new file mode 100644
index 0000000..a9c7cd4
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsDelete.php
@@ -0,0 +1,54 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\BadRequestException;
+use JsonApi\Errors\RecordNotFoundException;
+use JsonApi\JsonApiController;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardItemsDelete extends JsonApiController
+{
+ protected $allowedFilteringParameters = ['range_id'];
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $clipboard = \Clipboard::find($args['id']);
+ if (!$clipboard) {
+ throw new RecordNotFoundException('Clipboard not found');
+ }
+
+ $user = $this->getUser($request);
+ if (!Authority::canUpdateClipboard($user, $clipboard)) {
+ throw new \AccessDeniedException();
+ }
+
+ $item = null;
+ if (isset($args['itemId'])) {
+ $item = \ClipboardItem::find($args['itemId']);
+ } else {
+ $filtering = iterator_to_array($this->getQueryParameters()->getFilters());
+ if (!isset($filtering['range_id'])) {
+ throw new BadRequestException('No range_id filter given');
+ }
+ $item = \ClipboardItem::findOneBySQL(
+ 'clipboard_id = ? AND range_id = ?',
+ [$clipboard->id, $filtering['range_id']]
+ );
+ }
+
+ if (!$item) {
+ throw new RecordNotFoundException('Item not found');
+ }
+
+ if ($item->clipboard_id !== $clipboard->id) {
+ throw new BadRequestException('Item does not belong to clipboard');
+ }
+
+ $item->delete();
+
+ return $this->getCodeResponse(204);
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsShow.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsShow.php
new file mode 100644
index 0000000..3c91708
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardItemsShow.php
@@ -0,0 +1,28 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\Errors\RecordNotFoundException;
+use JsonApi\JsonApiController;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardItemsShow extends JsonApiController
+{
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $item = \ClipboardItem::find($args['id']);
+ if (!$item) {
+ throw new RecordNotFoundException();
+ }
+
+ $user = $this->getUser($request);
+ if (!Authority::canAccessClipboard($user, $item->clipboard)) {
+ throw new AuthorizationFailedException();
+ }
+
+ return $this->getContentResponse($item);
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardsCreate.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsCreate.php
new file mode 100644
index 0000000..57fd9b9
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsCreate.php
@@ -0,0 +1,46 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\JsonApiController;
+use JsonApi\Routes\ValidationTrait;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardsCreate extends JsonApiController
+{
+ use ValidationTrait;
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $user = $this->getUser($request);
+
+ if (!Authority::canCreateClipboard($user)) {
+ throw new AuthorizationFailedException();
+ }
+
+ $json = $this->validate($request, $args);
+
+ $clipboard = \Clipboard::create([
+ 'name' => $json['data']['attributes']['name'],
+ 'user_id' => $user->id,
+ ]);
+
+ return $this->getContentResponse($clipboard);
+ }
+
+ protected function validateResourceDocument($json, $data)
+ {
+ if (!self::arrayHas($json, 'data.attributes.name')) {
+ return 'No name for the clipboard defined';
+ }
+
+ if (!trim(self::arrayGet($json, 'data.attributes.name'))) {
+ return 'Name of the clipboard may not be empty';
+ }
+
+ return null;
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardsDelete.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsDelete.php
new file mode 100644
index 0000000..0897843
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsDelete.php
@@ -0,0 +1,31 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\Errors\RecordNotFoundException;
+use JsonApi\JsonApiController;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardsDelete extends JsonApiController
+{
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $clipboard = \Clipboard::find($args['id']);
+ if (!$clipboard) {
+ throw new RecordNotFoundException();
+ }
+
+ $user = $this->getUser($request);
+
+ if (!Authority::canDeleteClipboard($user, $clipboard)) {
+ throw new AuthorizationFailedException();
+ }
+
+ $clipboard->delete();
+
+ return $this->getCodeResponse(204);
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Clipboards/ClipboardsUpdate.php b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsUpdate.php
new file mode 100644
index 0000000..83d9539
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Clipboards/ClipboardsUpdate.php
@@ -0,0 +1,50 @@
+<?php
+namespace JsonApi\Routes\Clipboards;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\Errors\RecordNotFoundException;
+use JsonApi\JsonApiController;
+use JsonApi\Routes\ValidationTrait;
+use Psr\Http\Message\{
+ ResponseInterface as Response,
+ ServerRequestInterface as Request
+};
+
+final class ClipboardsUpdate extends JsonApiController
+{
+ use ValidationTrait;
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $clipboard = \Clipboard::find($args['id']);
+ if (!$clipboard) {
+ throw new RecordNotFoundException();
+ }
+
+ $user = $this->getUser($request);
+
+ if (!Authority::canUpdateClipboard($user, $clipboard)) {
+ throw new AuthorizationFailedException();
+ }
+
+ $json = $this->validate($request, $args);
+
+ $clipboard->name = $json['data']['attributes']['name'];
+ $clipboard->store();
+
+ return $this->getContentResponse($clipboard);
+ }
+
+ protected function validateResourceDocument($json, $data)
+ {
+ if (!self::arrayHas($json, 'data.attributes.name')) {
+ return 'No name for the clipboard defined';
+ }
+
+ if (!trim(self::arrayGet($json, 'data.attributes.name'))) {
+ return 'Name of the clipboard may not be empty';
+ }
+
+ return null;
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Consultations/SlotCreationCount.php b/lib/classes/JsonApi/Routes/Consultations/SlotCreationCount.php
new file mode 100644
index 0000000..c378771
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Consultations/SlotCreationCount.php
@@ -0,0 +1,105 @@
+<?php
+namespace JsonApi\Routes\Consultations;
+
+use ConsultationBlock;
+use JsonApi\Errors\BadRequestException;
+use JsonApi\NonJsonApiController;
+use Neomerx\JsonApi\Exceptions\JsonApiException;
+use Neomerx\JsonApi\Schema\ErrorCollection;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+
+final class SlotCreationCount extends NonJsonApiController
+{
+ public function __invoke(Request $request, Response $response, array $args)
+ {
+ $parameters = $request->getQueryParams();
+
+ $this->validateParameters($parameters);
+
+ // Determine duration of a slot and pause times
+ $slot_count = ConsultationBlock::countSlots(
+ strtotime($parameters['start']),
+ strtotime($parameters['end']),
+ $parameters['dow'],
+ $parameters['interval'],
+ $parameters['duration'],
+ $parameters['pause_time'] ?? null,
+ $parameters['pause_duration'] ?? null
+ );
+
+ $response->getBody()->write((string) $slot_count);
+ return $response->withAddedHeader('Content-Type', 'application/json');
+ }
+
+ private function validateParameters(array $parameters): void
+ {
+ $collection = new ErrorCollection();
+
+ foreach (['start', 'end', 'dow', 'interval', 'duration'] as $key) {
+ if (!isset($parameters[$key])) {
+ $collection->addQueryParameterError($key, 'Parameter is missing');
+ }
+ }
+
+ if (isset($parameters['start'], $parameters['end'])) {
+ $start = strtotime($parameters['start']);
+ $end = strtotime($parameters['end']);
+
+ if (!$start) {
+ $collection->addQueryParameterError('start', 'Parameter has invalid datetime format');
+ }
+
+ if (!$end) {
+ $collection->addQueryParameterError('end', 'Parameter has invalid datetime format');
+ }
+
+ if ($start && $end && $start > $end) {
+ $collection->addQueryParameterError('start', 'Datetime value of start must be before end');
+ }
+ }
+
+ if (
+ isset($parameters['dow'])
+ && (
+ !ctype_digit($parameters['dow'])
+ || $parameters['dow'] < 0
+ || $parameters['dow'] > 6
+ )
+ ) {
+ $collection->addQueryParameterError('dow', 'Parameter must be a number between 0 and 6');
+ }
+
+ if (
+ isset($parameters['interval'])
+ && (
+ !ctype_digit($parameters['interval'])
+ || $parameters['interval'] < 0
+ || $parameters['interval'] > 4
+ )
+ ) {
+ $collection->addQueryParameterError('interval', 'Parameter must be a number between 0 and 4');
+ }
+
+ if (
+ isset($parameters['duration'])
+ && (
+ !ctype_digit($parameters['duration'])
+ || $parameters['duration'] <= 0
+ )
+ ) {
+ $collection->addQueryParameterError('duration', 'Parameter must be a positive number');
+ }
+
+ if (
+ isset($parameters['pause_time'], $parameters['duration'])
+ && $parameters['pause_time'] < $parameters['duration']
+ ) {
+ $collection->addQueryParameterError('pause_time', 'The defined time to a pause is shorter than the duration of a slot.');
+ }
+
+ if (count($collection) > 0) {
+ throw new JsonApiException($collection);
+ }
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php b/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
index e676507..d913966 100644
--- a/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
+++ b/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
@@ -100,6 +100,20 @@ class UnitsCreate extends JsonApiController
'commentable' => 0
]);
+ \Courseware\Container::create([
+ 'structural_element_id' => $struct->id,
+ 'owner_id' => $user->id,
+ 'editor_id' => $user->id,
+ 'edit_blocker_id' => '',
+ 'position' => 0,
+ 'container_type' => 'list',
+
+ 'payload' => json_encode([
+ 'colspan' => 'full',
+ 'sections' => [['name' => _('erstes Element'), 'icon' => '','blocks' => []]]
+ ]),
+ ]);
+
$unit = \Courseware\Unit::create([
'range_id' => $range->getRangeId(),
'range_type' => $range->getRangeType(),
diff --git a/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php b/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
index 8f69d6a..773071e 100644
--- a/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
+++ b/lib/classes/JsonApi/Routes/Files/RangeFileRefsIndex.php
@@ -13,7 +13,7 @@ class RangeFileRefsIndex extends AbstractRangeIndex
$filerefs = [];
foreach ($filesAndFolders['files'] as $file_object) {
- if (method_exists($file_object, "getFileRef")) {
+ if (method_exists($file_object, 'getFileRef')) {
$filerefs[] = $file_object->getFileRef();
}
}
diff --git a/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php b/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
index 0ff0603..2ed1a23 100644
--- a/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
+++ b/lib/classes/JsonApi/Routes/Files/SubfilerefsIndex.php
@@ -2,6 +2,7 @@
namespace JsonApi\Routes\Files;
+use FileRef;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use JsonApi\Errors\AuthorizationFailedException;
@@ -28,8 +29,14 @@ class SubfilerefsIndex extends JsonApiController
throw new AuthorizationFailedException();
}
- $fileRefs = $folder->file_refs->getArrayCopy();
- list($offset, $limit) = $this->getOffsetAndLimit();
+ $fileRefs = array_map(
+ function (\FileType $file): FileRef {
+ return $file->getFileRef();
+ },
+ $folder->getFiles()
+ );
+
+ [$offset, $limit] = $this->getOffsetAndLimit();
return $this->getPaginatedContentResponse(
array_slice($fileRefs, $offset, $limit),
diff --git a/lib/classes/JsonApi/Routes/Files/SubfoldersIndex.php b/lib/classes/JsonApi/Routes/Files/SubfoldersIndex.php
index e8f4d13..f0ad18c 100644
--- a/lib/classes/JsonApi/Routes/Files/SubfoldersIndex.php
+++ b/lib/classes/JsonApi/Routes/Files/SubfoldersIndex.php
@@ -19,20 +19,31 @@ class SubfoldersIndex extends JsonApiController
*/
public function __invoke(Request $request, Response $response, $args)
{
- if (!$folder = \FileManager::getTypedFolder($args['id'])) {
+ $folder = \FileManager::getTypedFolder($args['id']);
+ if (!$folder) {
throw new RecordNotFoundException();
}
- if (!Authority::canShowFolder($this->getUser($request), $folder)) {
+ $user = $this->getUser($request);
+
+ if (!Authority::canShowFolder($user, $folder)) {
throw new AuthorizationFailedException();
}
- $subfolders = array_map(
- function ($subfolder) {
- return $subfolder->getTypedFolder();
+ $subfolders = array_reduce(
+ $folder->subfolders->getArrayCopy(),
+ function ($result, $subfolder) use ($user) {
+ $folder = $subfolder->getTypedFolder();
+
+ if (Authority::canShowFolder($user, $folder)) {
+ $result[] = $folder;
+ }
+
+ return $result;
},
- $folder->subfolders->getArrayCopy()
+ []
);
+
list($offset, $limit) = $this->getOffsetAndLimit();
return $this->getPaginatedContentResponse(