diff options
Diffstat (limited to 'app/routes/FileSystem.php')
| -rw-r--r-- | app/routes/FileSystem.php | 684 |
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; - } -} |
