aboutsummaryrefslogtreecommitdiff
path: root/app/routes/FileSystem.php
diff options
context:
space:
mode:
authorPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
committerPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
commit4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch)
tree5c07151ae61276d334e88f6309c30d439a85c12e /app/routes/FileSystem.php
parentda0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff)
parent97a188592c679890a25c37ab78463add76a52ff7 (diff)
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'app/routes/FileSystem.php')
-rw-r--r--app/routes/FileSystem.php684
1 files changed, 0 insertions, 684 deletions
diff --git a/app/routes/FileSystem.php b/app/routes/FileSystem.php
deleted file mode 100644
index 9abd713..0000000
--- a/app/routes/FileSystem.php
+++ /dev/null
@@ -1,684 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This class implements REST routes for the new Stud.IP file system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @license GNU General Public License Version 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * Partially based upon the Files.php source code from Jan-Hendrik Willms
- * (tleilax+studip@gmail.com) and mluzena@uos.de which is also
- * licensed under the terms of the GNU General Public License Version 2
- * or later.
- */
-
-class FileSystem extends \RESTAPI\RouteMap
-{
- // FILE REFERENCE AND FILE ROUTES:
-
- /**
- * Get a file reference object (metadata)
- * @get /file/:file_ref_id
- */
- public function getFileRef($file_ref_id)
- {
- return $this->filerefToJSON(
- $this->requireFileRef($file_ref_id),
- (bool) \Request::int('extended')
- );
- }
-
- /**
- * Get the data of a file by the ID of an associated FileRef object
- *
- * @get /file/:file_ref_id/download
- */
- public function getFileRefData($file_ref_id)
- {
- $file_ref = $this->requireFileRef($file_ref_id);
-
- // check if the current user has the permissions to read this file reference:
- $user = \User::findCurrent();
- if (!$file_ref->folder->getTypedFolder()->isFileDownloadable($file_ref_id, $user->id)) {
- $this->error(403, "You may not download the file reference with the id {$file_ref_id}");
- }
-
- // check if file exists:
- if (!$file_ref->file) {
- $this->error(500, 'File reference has no associated file object!');
- }
-
- $data_path = $file_ref->file->getPath();
- if (!file_exists($data_path)) {
- $this->error(500, "File was not found in the operating system's file system!");
- }
-
- $this->lastModified($file_ref->file->chdate);
- $this->sendFile($data_path, ['filename' => $file_ref->name]);
- }
-
- /**
- * Update file data using a FileReference to it.
- *
- * @post /file/:file_ref_id/update
- */
- public function updateFileData($file_ref_id)
- {
- // We only update the first file:
- $uploaded_file = array_shift($this->data['_FILES']);
-
- // FileManager::updateFileRef handles the whole file upload
- // and does all the necessary security checks:
- $result = \FileManager::updateFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent(),
- $uploaded_file,
- true,
- false
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while updating a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result);
- }
-
- /**
- * Edit a file reference.
- *
- * @put /file/:file_ref_id
- */
- public function editFileRef($file_ref_id)
- {
- $result = \FileManager::editFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent(),
- $this->data['name'],
- $this->data['description'],
- $this->data['content_term_of_use_id'],
- $this->data['license']
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while editing a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result);
- }
-
- /**
- * Copies a file reference.
- *
- * @post /file/:file_ref_id/copy/:destination_folder_id
- */
- public function copyFileRef($file_ref_id, $destination_folder_id)
- {
- $result = \FileManager::copyFile(
- $this->requireFileRef($file_ref_id)->getFileType(),
- $this->requireFolder($destination_folder_id)->getTypedFolder(),
- \User::findCurrent()
- );
-
- if (!($result instanceof \FileType)) {
- $this->error(500, 'Error while copying a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result->getFileRef());
- }
-
- /**
- * Moves a file reference.
- *
- * @post /file/:file_ref_id/move/:destination_folder_id
- */
- public function moveFileRef($file_ref_id, $destination_folder_id)
- {
- $result = \FileManager::moveFile(
- $this->requireFileRef($file_ref_id)->getFileType(),
- $this->requireFolder($destination_folder_id)->getTypedFolder(),
- \User::findCurrent()
- );
-
- if (!($result instanceof \FileType)) {
- $this->error(500, 'Error while moving a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result->getFileRef());
- }
-
- /**
- * Deletes a file reference.
- *
- * @delete /file/:file_ref_id
- */
- public function deleteFileRef($file_ref_id)
- {
- $result = \FileManager::deleteFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while deleting a file reference: ' . implode(' ', $result));
- }
-
- $this->halt(200);
- }
-
- /**
- * Upload file to given folder.
- * file data has to be attached as multipart/form-data
- *
- * @post /file/:folder_id
- */
- public function uploadFile($folder_id)
- {
- $typed_folder = $this->requireFolder($folder_id)->getTypedFolder();
- if (isset($this->data['_FILES'])) {
- $file_data = array_map(function ($a) {
- return is_array($a) ? $a : [$a];
- }, array_shift($this->data['_FILES']));
- }
- if (is_array($file_data)) {
- $validated_files = \FileManager::handleFileUpload(
- $file_data,
- $typed_folder,
- $this->requireUser()->id
- );
-
- if (count($validated_files['error']) > 0) {
- $this->error(500, 'Error while uploading files: ' . implode(' ', $validated_files['error']));
- }
-
- $uploaded_files = \SimpleCollection::createFromArray($validated_files['files']);
- $default_license = \ContentTermsOfUse::findDefault();
- $uploaded_files->setValue('content_terms_of_use_id', $default_license->id);
- $uploaded_files->store();
- if (count($uploaded_files) === 1) {
- $result = $this->filerefToJSON($uploaded_files->first());
- } else {
- $result = $uploaded_files->map(function ($f) {
- return $this->filerefToJSON($f);
- });
- }
- $this->halt(201, [], $result);
- } else {
- $this->error(400, 'No files found in request.');
- }
- }
-
- // FOLDER ROUTES:
-
- /**
- * Returns a list of defined folder types, separated by range type.
- * @get /studip/file_system/folder_types
- */
- public function getDefinedFolderTypes()
- {
- return \FileManager::getFolderTypes();
- }
-
- /**
- * Get a folder object with its file references, subdirectories and the permissions for the user who has made the API call.
- * @get /folder/:folder_id
- */
- public function getFolder($folder_id)
- {
- return $this->folderToJSON(
- $this->requireFolder($folder_id),
- true
- );
- }
-
- /**
- * Creates a new folder inside of another folder and returns the new object on success.
- * @post /folder/:parent_folder_id/new_folder
- */
- public function createNewFolder($parent_folder_id)
- {
- $user = \User::findCurrent();
- $parent = $this->requireTypedFolder($parent_folder_id);
-
- if (!$parent->isWritable($user->id)) {
- $this->error(403, 'You are not permitted to create a subfolder in the parent folder!');
- }
-
- $result = \FileManager::createSubFolder(
- $parent,
- $user,
- 'StandardFolder', //to be extended
- $this->data['name'],
- $this->data['description']
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while creating a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($result->getId())
- );
- }
-
- /**
- * Get a list with all FileRef objects of a folder.
- * @get /folder/:folder_id/files
- */
- public function getFileRefsOfFolder($folder_id)
- {
- $folder = $this->requireFolder($folder_id);
-
- $query = "folder_id = :folder_id ORDER BY name ASC";
- $parameters[':folder_id'] = $folder->id;
-
- if ($this->limit || $this->offset) {
- $query .= " LIMIT :limit OFFSET :offset";
- $parameters[':limit'] = $this->limit;
- $parameters[':offset'] = $this->offset;
- }
-
- $file_refs = \FileRef::findAndMapBySql(function (\FileRef $ref) {
- return $this->filerefToJSON($ref);
- }, $query, $parameters);
-
- return $this->paginated(
- $file_refs,
- \FileRef::countByFolder_id($folder->id),
- ['folder_id' => $folder->id]
- );
- }
-
-
- /**
- * Get a list with all FileRef objects of a folder.
- * @get /folder/:folder_id/subfolders
- */
- public function getSubfoldersOfFolder($folder_id)
- {
- $user = $this->requireUser();
- $folder = $this->requireFolder($folder_id);
-
- $query = "parent_id = :parent_id ORDER BY name ASC";
- $parameters = [':parent_id' => $folder->id];
-
- if ($this->limit || $this->offset) {
- $query .= " LIMIT :limit OFFSET :offset";
- $parameters[':limit'] = $this->limit;
- $parameters[':offset'] = $this->offset;
- }
-
- $subfolders = \Folder::findAndMapBySql(function (\Folder $subfolder) use ($user) {
- $type = $subfolder->getTypedFolder();
- if (!$type || !$type->isVisible($user->id)) {
- return false;
- }
- return $this->folderToJSON($subfolder);
- }, $query, $parameters);
-
- return $this->paginated(
- array_filter($subfolders),
- \Folder::countByParent_id($folder_id),
- ['folder_id' => $folder_id]
- );
- }
-
- /**
- * Get a list with permissions the current user has for a folder.
- * @get /folder/:folder_id/permissions
- */
- public function getFolderPermissions($folder_id)
- {
- $user = $this->requireUser();
- $folder = $this->requireFolder($folder_id);
-
- // read permissions of the user and return them:
- return array_merge([
- 'folder_id' => $folder->id,
- 'user_id' => $user->id,
- ], $this->folderPermissionsToJSON($folder));
- }
-
- /**
- * Allows editing the name or the description (or both) of a folder.
- *
- * @put /folder/:folder_id
- */
- public function editFolder($folder_id)
- {
- if (isset($this->data['name']) && !$this->data['name']) {
- $this->error(400, "The name for the folder with the id {$folder_id} must not be empty!");
- }
-
- $user = $this->requireUser();
- $typed_folder = $this->requireTypedFolder($folder_id);
-
- if (!$typed_folder->isEditable($user->id)) {
- $this->error(403, "You may not edit the folder with id {$folder_id}!");
- }
-
- if (!$typed_folder instanceof \StandardFolder) {
- $this->error(501, "Editing is only allowed for folders of type StandardFolder for now!");
- }
-
- if ($this->data['name']) {
- $typed_folder->name = $this->data['name'];
- }
- if (isset($this->data['description'])) {
- $typed_folder->description = $this->data['description'] ?: '';
- }
-
- if (!$typed_folder->store()) {
- $this->error(500, "Could not store folder with id {$folder_id}!");
- }
-
- return $this->folderToJSON(
- $this->requireFolder($folder_id)
- );
- }
-
- /**
- * Copies a folder into another folder.
- *
- * @post /folder/:folder_id/copy/:destination_folder_id
- */
- public function copyFolder($folder_id, $destination_folder_id)
- {
- $result = \FileManager::copyFolder(
- $this->requireTypedFolder($folder_id),
- $this->requireTypedFolder($destination_folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while copying a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($result->getId())
- );
- }
-
-
- /**
- * Move a folder into another folder.
- * @post /folder/:folder_id/move/:destination_folder_id
- */
- public function moveFolder($folder_id, $destination_folder_id)
- {
- $result = \FileManager::moveFolder(
- $this->requireTypedFolder($folder_id),
- $this->requireTypedFolder($destination_folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while moving a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($folder_id)
- );
- }
-
-
- /**
- * Deletes a folder.
- *
- * @delete /folder/:folder_id
- */
- public function deleteFolder($folder_id)
- {
- $result = \FileManager::deleteFolder(
- $this->requireTypedFolder($folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while deleting a folder: ' . implode(' ', $result));
- }
-
- $this->halt(200);
- }
-
- // RELATED OBJECT ROUTES:
-
- /**
- * Get a collection of all ContentTermsOfUse objects
- *
- * @get /studip/content_terms_of_use_list
- */
- public function getContentTermsOfUseList()
- {
- $objects = \ContentTermsOfUse::findBySql(
- '1 ORDER BY name ASC LIMIT :limit OFFSET :offset',
- ['limit' => $this->limit, 'offset' => $this->offset]
- );
-
- return $this->paginated(
- array_map([$this, 'termsOfUseToJSON'], $objects),
- \ContentTermsOfUse::countBySql('1')
- );
- }
-
- // UTILITY METHODS
-
- /**
- * Requires a valid user object.
- * @return \User object
- */
- private function requireUser()
- {
- return \User::findCurrent();
- }
-
- /**
- * Requires a valid file reference object
- * @param mixed $id_or_object Either a file reference id or object
- * @return \FileRef object
- */
- private function requireFileRef($id_or_object)
- {
- if ($id_or_object instanceof \FileRef) {
- $file_ref = $id_or_object;
- } else {
- //check if the file_id references a file reference object:
- $file_ref = \FileRef::find($id_or_object);
- if (!$file_ref) {
- $this->notFound("File reference with id {$id_or_object} not found!");
- }
- }
-
- // check if the file reference is placed inside a folder.
- // (must be present to check for permissions)
- if (!$file_ref->folder) {
- $this->error(500, "File reference with id {$file_ref->id} has no folder!");
- }
-
- $typed_folder = $file_ref->folder->getTypedFolder();
- if (!$typed_folder) {
- $this->error(500, "The folder of file reference with id {$file_ref->id} has no folder type!");
- }
-
- //check if the current user has the permissions to read this file reference:
- if (!$typed_folder->isReadable($this->requireUser()->id)) {
- $this->error(403, "You are not permitted to read the file reference with id {$file_ref->id}!");
- }
-
- return $file_ref;
- }
-
- /**
- * Converts a file reference object to JSON.
- * @param \FileRef $ref File reference object
- * @param boolean $extended Extended output? (includes folder, owner and terms of use)
- * @return array representation for json encoding
- */
- private function filerefToJSON(\FileRef $ref, $extended = false)
- {
- $user = $this->requireUser();
- $typed_folder = $ref->folder->getTypedFolder();
- $filetype = $ref->getFileType();
-
- $result = array_merge($ref->toRawArray(), [
- 'size' => (int) $ref->file->size,
- 'mime_type' => $ref->file->mime_type,
- 'storage' => $ref->file->filetype === "URLFile" ? "url" : "disk",
-
- 'is_readable' => $typed_folder->isReadable($user->id),
- 'is_downloadable' => $filetype->isDownloadable($user->id),
- 'is_editable' => $filetype->isEditable($user->id),
- 'is_writable' => $filetype->isWritable($user->id),
- ]);
-
- $result['downloads'] = (int) $result['downloads'];
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- if ($result['storage'] === 'url') {
- $result['url'] = $ref->getFileType()->getDownloadURL();
- }
-
- if ($extended) {
- //folder does exist (since we checked for its existence above)
- $result['folder'] = $this->folderToJSON($ref->folder);
-
- if ($ref->owner) {
- $result['owner'] = User::getMiniUser($this, $ref->owner);
- }
-
- //$result['license'] = $file_ref->license; //to be activated when licenses are defined
-
- if ($ref->terms_of_use) {
- $result['terms_of_use'] = $this->termsOfUseToJSON($ref->terms_of_use);
- }
- }
-
- return $result;
- }
-
- /**
- * Requires a valid folder object
- * @param mixed $id_or_object Either a folder id or object
- * @return Folder object
- */
- private function requireFolder($id_or_object)
- {
- if ($id_or_object instanceof \Folder) {
- $folder = $id_or_object;
- } else {
- $folder = \Folder::find($id_or_object);
- if (!$folder) {
- $this->notFound("Folder with id {$id_or_object} not found!");
- }
- }
-
- $typed_folder = $folder->getTypedFolder();
- if (!$typed_folder) {
- $this->error(500, "Cannot find folder type of folder with id {$folder->id}!");
- return;
- }
-
- if (!$typed_folder->isReadable($this->requireUser()->id)) {
- $this->error(403, "You are not allowed to read the contents of the folder with the id {$folder->id}!");
- }
-
- return $folder;
- }
-
- /**
- * Requires a valid typed folder object
- * @param mixed $id_or_object Either a folder id or object
- * @return FolderType instance
- */
- private function requireTypedFolder($id_or_object)
- {
- return $this->requireFolder($id_or_object)->getTypedFolder();
- }
-
- /**
- * Converts a given folder to JSON.
- * @param Folder $folder Folder object
- * @param boolean $extended Extended output? (includes subfolders and file references)
- * @return array representation for json encoding
- */
- private function folderToJSON(\Folder $folder, $extended = false)
- {
- $result = $this->folderPermissionsToJSON($folder);
-
- if ($result['is_readable']) {
- $result = array_merge($folder->toRawArray(), $result);
-
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- //The field "data_content" must be handled differently
- //than the other fields since it contains JSON data.
- $data_content = json_decode($folder->data_content);
- $result['data_content'] = $data_content;
-
- if ($extended) {
- $user = $this->requireUser();
-
- $result['subfolders'] = [];
- foreach ($folder->subfolders as $subfolder) {
- if (!$subfolder->getTypedFolder()->isVisible($user->id)) {
- continue;
- }
- $result['subfolders'][] = $this->folderToJSON($subfolder);
- }
-
- $result['file_refs'] = [];
- foreach ($folder->getTypedFolder()->getFiles() as $file) {
- if (method_exists($file,"getFileRef")) {
- $result['file_refs'][] = $this->filerefToJSON(
- $file->getFileRef()
- );
- }
- }
- }
- }
-
- return $result;
- }
-
- /**
- * Converts permissions of a folder to JSON.
- * @param Folder $folder Folder object
- * @param User $user User object to check permissions against
- * @return array representation for json encoding
- */
- private function folderPermissionsToJSON(\Folder $folder)
- {
- $user = $this->requireUser();
- $type = $folder = $folder->getTypedFolder();
- if (!$type) {
- $this->error(500, 'Folder type not found!');
- }
-
- return [
- 'is_visible' => $type->isVisible($user->id),
- 'is_readable' => $type->isReadable($user->id),
- 'is_writable' => $type->isWritable($user->id),
- ];
- }
-
- /**
- * Converts a terms of use object to JSON.
- * @param ContentTermsOfUse $object Object
- * @return array representation for json encoding
- */
- private function termsOfUseToJSON(\ContentTermsOfUse $object)
- {
- $result = $object->toRawArray();
-
- $result['is_default'] = (bool) $result['is_default'];
-
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- return $result;
- }
-}