diff --git a/app/V1Module/router/RouterFactory.php b/app/V1Module/router/RouterFactory.php index 3a3bd57b..5c7f3d88 100644 --- a/app/V1Module/router/RouterFactory.php +++ b/app/V1Module/router/RouterFactory.php @@ -18,6 +18,13 @@ class RouterFactory { use Nette\StaticClass; + private static $strictMode = false; + + public static function setStrictMode(bool $strict = true): void + { + self::$strictMode = $strict; + } + /** * Create router with all routes for V1 module. * @return Router @@ -177,26 +184,28 @@ private static function createExercisesRoutes(string $prefix): RouteList // special download route for file link by its key $router[] = new GetRoute("$prefix//file-download/", "UploadedFiles:downloadExerciseFileLinkByKey"); - // deprecated routes for supplementary-files (replaced with `files`) - $router[] = new GetRoute("$prefix//supplementary-files", "ExerciseFiles:getExerciseFiles"); - $router[] = new PostRoute("$prefix//supplementary-files", "ExerciseFiles:uploadExerciseFiles"); - $router[] = new DeleteRoute( - "$prefix//supplementary-files/", - "ExerciseFiles:deleteExerciseFile" - ); - $router[] = new GetRoute( - "$prefix//supplementary-files/download-archive", - "ExerciseFiles:downloadExerciseFilesArchive" - ); - - // deprecated (will be removed with AttachmentFile entity, unified with exercise-files) - $router[] = new GetRoute("$prefix//attachment-files", "ExerciseFiles:getAttachmentFiles"); - $router[] = new PostRoute("$prefix//attachment-files", "ExerciseFiles:uploadAttachmentFiles"); - $router[] = new DeleteRoute("$prefix//attachment-files/", "ExerciseFiles:deleteAttachmentFile"); - $router[] = new GetRoute( - "$prefix//attachment-files/download-archive", - "ExerciseFiles:downloadAttachmentFilesArchive" - ); + if (!self::$strictMode) { + // deprecated routes for supplementary-files (replaced with `files`) + $router[] = new GetRoute("$prefix//supplementary-files", "ExerciseFiles:getExerciseFiles"); + $router[] = new PostRoute("$prefix//supplementary-files", "ExerciseFiles:uploadExerciseFiles"); + $router[] = new DeleteRoute( + "$prefix//supplementary-files/", + "ExerciseFiles:deleteExerciseFile" + ); + $router[] = new GetRoute( + "$prefix//supplementary-files/download-archive", + "ExerciseFiles:downloadExerciseFilesArchive" + ); + + // deprecated (will be removed with AttachmentFile entity, unified with exercise-files) + $router[] = new GetRoute("$prefix//attachment-files", "ExerciseFiles:getAttachmentFiles"); + $router[] = new PostRoute("$prefix//attachment-files", "ExerciseFiles:uploadAttachmentFiles"); + $router[] = new DeleteRoute("$prefix//attachment-files/", "ExerciseFiles:deleteAttachmentFile"); + $router[] = new GetRoute( + "$prefix//attachment-files/download-archive", + "ExerciseFiles:downloadAttachmentFilesArchive" + ); + } $router[] = new GetRoute("$prefix//tests", "ExercisesConfig:getTests"); $router[] = new PostRoute("$prefix//tests", "ExercisesConfig:setTests"); @@ -483,8 +492,10 @@ private static function createUploadedFilesRoutes(string $prefix): RouteList $router[] = new GetRoute("$prefix//content", "UploadedFiles:content"); $router[] = new GetRoute("$prefix//digest", "UploadedFiles:digest"); - // deprecated (should be handled by generic download) - $router[] = new GetRoute("$prefix/supplementary-file//download", "UploadedFiles:downloadExerciseFile"); + if (!self::$strictMode) { + // deprecated (should be handled by generic download) + $router[] = new GetRoute("$prefix/supplementary-file//download", "UploadedFiles:downloadExerciseFile"); + } return $router; } @@ -600,10 +611,12 @@ private static function createPipelinesRoutes(string $prefix): RouteList $router[] = new DeleteRoute("$prefix//exercise-files/", "Pipelines:deleteExerciseFile"); $router[] = new GetRoute("$prefix//exercises", "Pipelines:getPipelineExercises"); - // deprecated routes for supplementary files - $router[] = new GetRoute("$prefix//supplementary-files", "Pipelines:getExerciseFiles"); - $router[] = new PostRoute("$prefix//supplementary-files", "Pipelines:uploadExerciseFiles"); - $router[] = new DeleteRoute("$prefix//supplementary-files/", "Pipelines:deleteExerciseFile"); + if (!self::$strictMode) { + // deprecated routes for supplementary files + $router[] = new GetRoute("$prefix//supplementary-files", "Pipelines:getExerciseFiles"); + $router[] = new PostRoute("$prefix//supplementary-files", "Pipelines:uploadExerciseFiles"); + $router[] = new DeleteRoute("$prefix//supplementary-files/", "Pipelines:deleteExerciseFile"); + } return $router; } @@ -674,8 +687,10 @@ private static function createWorkerFilesRoutes(string $prefix): RouteList $router[] = new GetRoute("$prefix/exercise-file/", "WorkerFiles:downloadExerciseFile"); $router[] = new PutRoute("$prefix/result//", "WorkerFiles:uploadResultsFile"); - // deprecated route for supplementary files - $router[] = new GetRoute("$prefix/supplementary-file/", "WorkerFiles:downloadExerciseFile"); + if (!self::$strictMode) { + // deprecated route for supplementary files + $router[] = new GetRoute("$prefix/supplementary-file/", "WorkerFiles:downloadExerciseFile"); + } return $router; } diff --git a/app/helpers/Swagger/AnnotationHelper.php b/app/helpers/Swagger/AnnotationHelper.php index ed20bce1..3b8fea45 100644 --- a/app/helpers/Swagger/AnnotationHelper.php +++ b/app/helpers/Swagger/AnnotationHelper.php @@ -470,6 +470,7 @@ public static function filterAnnotations(array $annotations, string $type) */ public static function getRoutesMetadata(): array { + RouterFactory::setStrictMode(); // no deprecated (duplicate) routes $router = RouterFactory::createRouter(); // find all route object using a queue diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 117780d8..f5f5eaf2 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1285,194 +1285,6 @@ paths: responses: '200': description: 'Placeholder response' - '/v1/exercises/{id}/supplementary-files': - get: - summary: 'Get list of all exercise files for an exercise' - description: 'Get list of all exercise files for an exercise' - operationId: exerciseFilesPresenterActionGetExerciseFiles - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - post: - summary: 'Associate exercise files with an exercise and upload them to remote file server' - description: 'Associate exercise files with an exercise and upload them to remote file server' - operationId: exerciseFilesPresenterActionUploadExerciseFiles - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - requestBody: - content: - application/json: - schema: - required: - - files - properties: - files: - description: 'Identifiers of exercise files' - type: string - nullable: true - type: object - responses: - '200': - description: 'Placeholder response' - '/v1/exercises/{id}/supplementary-files/{fileId}': - delete: - summary: 'Delete exercise file with given id' - description: 'Delete exercise file with given id' - operationId: exerciseFilesPresenterActionDeleteExerciseFile - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - - - name: fileId - in: path - description: 'identification of file' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - '/v1/exercises/{id}/supplementary-files/download-archive': - get: - summary: 'Download archive containing all files for exercise.' - description: 'Download archive containing all files for exercise.' - operationId: exerciseFilesPresenterActionDownloadExerciseFilesArchive - parameters: - - - name: id - in: path - description: 'of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - '/v1/exercises/{id}/attachment-files': - get: - summary: 'Get a list of all attachment files for an exercise [DEPRECATED]' - description: "Get a list of all attachment files for an exercise\n[DEPRECATED]: attachment files were unified with exercise files" - operationId: exerciseFilesPresenterActionGetAttachmentFiles - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - deprecated: true - post: - summary: 'Associate attachment exercise files with an exercise [DEPRECATED]' - description: "Associate attachment exercise files with an exercise\n[DEPRECATED]: attachment files were unified with exercise files" - operationId: exerciseFilesPresenterActionUploadAttachmentFiles - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - requestBody: - content: - application/json: - schema: - required: - - files - properties: - files: - description: 'Identifiers of attachment files' - type: string - nullable: true - type: object - responses: - '200': - description: 'Placeholder response' - deprecated: true - '/v1/exercises/{id}/attachment-files/{fileId}': - delete: - summary: 'Delete attachment exercise file with given id [DEPRECATED]' - description: "Delete attachment exercise file with given id\n[DEPRECATED]: attachment files were unified with exercise files" - operationId: exerciseFilesPresenterActionDeleteAttachmentFile - parameters: - - - name: id - in: path - description: 'identification of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - - - name: fileId - in: path - description: 'identification of file' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - deprecated: true - '/v1/exercises/{id}/attachment-files/download-archive': - get: - summary: 'Download archive containing all attachment files for exercise. [DEPRECATED]' - description: "Download archive containing all attachment files for exercise.\n[DEPRECATED]: attachment files were unified with exercise files" - operationId: exerciseFilesPresenterActionDownloadAttachmentFilesArchive - parameters: - - - name: id - in: path - description: 'of exercise' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - deprecated: true '/v1/exercises/{id}/tests': get: summary: 'Get tests for exercise based on given identification.' @@ -5104,25 +4916,6 @@ paths: responses: '200': description: 'Placeholder response' - '/v1/uploaded-files/supplementary-file/{id}/download': - get: - summary: 'Download exercise file [DEPRECATED]' - description: "Download exercise file\n[DEPRECATED]: use generic uploaded-file download endpoint instead" - operationId: uploadedFilesPresenterActionDownloadExerciseFile - parameters: - - - name: id - in: path - description: 'Identifier of the file' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - deprecated: true /v1/users: get: summary: 'Get a list of all users matching given filters in given pagination rage. The result conforms to pagination protocol.' @@ -6428,80 +6221,6 @@ paths: responses: '200': description: 'Placeholder response' - '/v1/pipelines/{id}/supplementary-files': - get: - summary: 'Get list of all exercise files for a pipeline' - description: 'Get list of all exercise files for a pipeline' - operationId: pipelinesPresenterActionGetExerciseFiles - parameters: - - - name: id - in: path - description: 'identification of pipeline' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' - post: - summary: 'Associate exercise files with a pipeline and upload them to remote file server' - description: 'Associate exercise files with a pipeline and upload them to remote file server' - operationId: pipelinesPresenterActionUploadExerciseFiles - parameters: - - - name: id - in: path - description: 'identification of pipeline' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - requestBody: - content: - application/json: - schema: - required: - - files - properties: - files: - description: 'Identifiers of exercise files' - type: string - nullable: true - type: object - responses: - '200': - description: 'Placeholder response' - '/v1/pipelines/{id}/supplementary-files/{fileId}': - delete: - summary: 'Delete exercise file with given id' - description: 'Delete exercise file with given id' - operationId: pipelinesPresenterActionDeleteExerciseFile - parameters: - - - name: id - in: path - description: 'identification of pipeline' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - - - name: fileId - in: path - description: 'identification of file' - required: true - schema: - type: string - pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - nullable: false - responses: - '200': - description: 'Placeholder response' /v1/extensions/sis/status/: get: summary: 'Check SIS status for the current user. [DEPRECATED]' @@ -7358,23 +7077,6 @@ paths: responses: '200': description: 'Placeholder response' - '/v1/worker-files/supplementary-file/{hash}': - get: - summary: 'Sends over an exercise file (a data file required by the tests).' - description: 'Sends over an exercise file (a data file required by the tests).' - operationId: workerFilesPresenterActionDownloadExerciseFile - parameters: - - - name: hash - in: path - description: 'identification of the exercise file' - required: true - schema: - type: string - nullable: false - responses: - '200': - description: 'Placeholder response' '/v1/async-jobs/{id}': get: summary: 'Retrieves details about particular async job.' diff --git a/recodex-api.spec b/recodex-api.spec index 921047d3..dca12e0b 100644 --- a/recodex-api.spec +++ b/recodex-api.spec @@ -2,8 +2,8 @@ %define short_name api %define install_dir /opt/%{name} %define version 2.21.0 -%define unmangled_version e9d22c1efcb382e27c45ddda6ebe6bcce552a46d -%define release 1 +%define unmangled_version 72e885b67bbfaa7c680ee0b6b23845cc21eecd6d +%define release 2 Summary: ReCodEx core API component Name: %{name}