From cd95e8335c55ecf098e6dd7b4b302b171955f9de Mon Sep 17 00:00:00 2001 From: Jose Andres Tejerina Date: Tue, 18 Nov 2025 19:35:29 -0300 Subject: [PATCH 1/3] feat: Extend Swagger Coverage for controller OAuth2ElectionsApiController --- .../Main/OAuth2ElectionsApiController.php | 431 ++++++++++++++++-- app/Swagger/CandidatesListSchema.php | 32 ++ app/Swagger/ElectionSchemas.php | 58 +++ app/Swagger/ElectionsSchemas.php | 7 - app/Swagger/NominationSchema.php | 79 ++++ app/Swagger/models/CandidateSchema.php | 105 +++++ app/Swagger/models/ElectionSchema.php | 102 +++++ app/Swagger/security/ElectionOAuth2Schema.php | 26 ++ 8 files changed, 803 insertions(+), 37 deletions(-) create mode 100644 app/Swagger/CandidatesListSchema.php create mode 100644 app/Swagger/ElectionSchemas.php delete mode 100644 app/Swagger/ElectionsSchemas.php create mode 100644 app/Swagger/NominationSchema.php create mode 100644 app/Swagger/models/CandidateSchema.php create mode 100644 app/Swagger/models/ElectionSchema.php create mode 100644 app/Swagger/security/ElectionOAuth2Schema.php diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php index e42e97351..7b3d0cf1e 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php @@ -15,12 +15,15 @@ use App\Models\Foundation\Elections\Election; use App\Models\Foundation\Elections\IElectionsRepository; use App\ModelSerializers\SerializerUtils; +use App\Security\ElectionScopes; use App\Services\Model\IElectionService; use libs\utils\HTMLCleaner; use models\oauth2\IResourceServerContext; use ModelSerializers\SerializerRegistry; use utils\Filter; use utils\PagingInfo; +use OpenApi\Attributes as OA; +use Symfony\Component\HttpFoundation\Response; /** * Class OAuth2ElectionsApiController @@ -50,9 +53,60 @@ public function __construct $this->service = $service; } - /** - * @return mixed - */ + #[OA\Get( + path: "/api/v1/elections", + operationId: "getAllElections", + description: "Get all elections with pagination and filtering", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::ReadAllElections]]], + parameters: [ + new OA\Parameter( + name: "page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 1), + description: "Page number" + ), + new OA\Parameter( + name: "per_page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 20), + description: "Items per page" + ), + new OA\Parameter( + name: "filter", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Filter by name, opens, or closes (epoch format). Example: name[]=Test&opens[from]=1634567890" + ), + new OA\Parameter( + name: "order", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Order by: name, id, opens, or closes. Example: name,-opens" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Elections list retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/ElectionsList") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getAll() { return $this->_getAll( @@ -97,9 +151,30 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) { ); } - /** - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Get( + path: "/api/v1/elections/current", + operationId: "getCurrentElection", + description: "Get the current active election", + tags: ["Elections (Public)"], + parameters: [ + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Current election retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/Election") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getCurrent() { return $this->processRequest(function () { @@ -122,10 +197,38 @@ public function getCurrent() }); } - /** - * @param $election_id - * @return mixed - */ + #[OA\Get( + path: "/api/v1/elections/{election_id}", + operationId: "getElectionById", + description: "Get election by ID", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::ReadAllElections]]], + parameters: [ + new OA\Parameter( + name: "election_id", + in: "path", + required: true, + schema: new OA\Schema(type: "integer", format: "int64"), + description: "Election ID" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Election retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/Election") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Election not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getById($election_id) { return $this->processRequest(function () use ($election_id) { @@ -148,9 +251,58 @@ public function getById($election_id) }); } - /** - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Get( + path: "/api/v1/elections/current/candidates", + operationId: "getCurrentElectionCandidates", + description: "Get all accepted candidates for the current election. Supports expand parameter to include member and/or election objects", + tags: ["Elections (Public)"], + parameters: [ + new OA\Parameter( + name: "page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 1), + description: "Page number" + ), + new OA\Parameter( + name: "per_page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 20), + description: "Items per page" + ), + new OA\Parameter( + name: "filter", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Filter by first_name, last_name, or full_name" + ), + new OA\Parameter( + name: "order", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Order by first_name or last_name" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships: member, election (comma-separated)" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Current election candidates retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getCurrentCandidates() { @@ -199,10 +351,67 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) ); } - /** - * @return \Illuminate\Http\JsonResponse|mixed - */ - public function getElectionCandidates($election_id) + #[OA\Get( + path: "/api/v1/elections/{election_id}/candidates", + operationId: "getElectionCandidates", + description: "Get all accepted candidates for a specific election. Supports expand parameter to include member and/or election objects", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::ReadAllElections]]], + parameters: [ + new OA\Parameter( + name: "election_id", + in: "path", + required: true, + schema: new OA\Schema(type: "integer", format: "int64"), + description: "Election ID" + ), + new OA\Parameter( + name: "page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 1), + description: "Page number" + ), + new OA\Parameter( + name: "per_page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 20), + description: "Items per page" + ), + new OA\Parameter( + name: "filter", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Filter by first_name, last_name, or full_name" + ), + new OA\Parameter( + name: "order", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Order by first_name or last_name" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships: member, election (comma-separated)" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Election candidates retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Election not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + public function getElectionCandidates(int $election_id) { $election = $this->repository->getById(intval($election_id)); @@ -250,9 +459,58 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) ); } - /** - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Get( + path: "/api/v1/elections/current/candidates/gold", + operationId: "getCurrentGoldCandidates", + description: "Get all gold (featured) candidates for the current election. Supports expand parameter to include member and/or election objects", + tags: ["Elections (Public)"], + parameters: [ + new OA\Parameter( + name: "page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 1), + description: "Page number" + ), + new OA\Parameter( + name: "per_page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 20), + description: "Items per page" + ), + new OA\Parameter( + name: "filter", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Filter by first_name, last_name, or full_name" + ), + new OA\Parameter( + name: "order", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Order by first_name or last_name" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships: member, election (comma-separated)" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Gold candidates retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getCurrentGoldCandidates() { @@ -301,6 +559,66 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) ); } + #[OA\Get( + path: "/api/v1/elections/{election_id}/candidates/gold", + operationId: "getElectionGoldCandidates", + description: "Get all gold (featured) candidates for a specific election. Supports expand parameter to include member and/or election objects", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::ReadAllElections]]], + parameters: [ + new OA\Parameter( + name: "election_id", + in: "path", + required: true, + schema: new OA\Schema(type: "integer", format: "int64"), + description: "Election ID" + ), + new OA\Parameter( + name: "page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 1), + description: "Page number" + ), + new OA\Parameter( + name: "per_page", + in: "query", + required: false, + schema: new OA\Schema(type: "integer", default: 20), + description: "Items per page" + ), + new OA\Parameter( + name: "filter", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Filter by first_name, last_name, or full_name" + ), + new OA\Parameter( + name: "order", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Order by first_name or last_name" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships: member, election (comma-separated)" + ), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Gold candidates retrieved successfully", + content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + ), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Election not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getElectionGoldCandidates($election_id) { @@ -349,11 +667,29 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) ); } - use GetAndValidateJsonPayload; - - /** - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Put( + path: "/api/v1/elections/current/candidates/me", + operationId: "updateMyCandidateProfile", + description: "Update current user's candidate profile for the current election", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::WriteMyCandidateProfile]]], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: "#/components/schemas/CandidateProfileUpdateRequest") + ), + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Candidate profile updated successfully", + content: new OA\JsonContent(ref: "#/components/schemas/Member") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden - User not authenticated"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function updateMyCandidateProfile() { return $this->processRequest(function () { @@ -393,11 +729,46 @@ public function updateMyCandidateProfile() }); } - /** - * @param $candidate_id - * @return \Illuminate\Http\JsonResponse|mixed - */ - public function nominateCandidate($candidate_id) + #[OA\Post( + path: "/api/v1/elections/current/candidates/{candidate_id}", + operationId: "nominateCandidate", + description: "Nominate a candidate for the current election. Supports expand parameter to include related objects (election, candidate, nominator)", + tags: ["Elections"], + security: [['election_oauth2' => [ElectionScopes::NominatesCandidates]]], + parameters: [ + new OA\Parameter( + name: "candidate_id", + in: "path", + required: true, + schema: new OA\Schema(type: "integer", format: "int64"), + description: "Candidate ID to nominate" + ), + new OA\Parameter( + name: "expand", + in: "query", + required: false, + schema: new OA\Schema(type: "string"), + description: "Expand relationships: election, candidate, nominator (comma-separated)" + ), + ], + requestBody: new OA\RequestBody( + required: false, + content: new OA\JsonContent(ref: "#/components/schemas/NominationRequest") + ), + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "Candidate nominated successfully", + content: new OA\JsonContent(ref: "#/components/schemas/Nomination") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden - User not authenticated"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Candidate or current election not found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + public function nominateCandidate(int $candidate_id) { return $this->processRequest(function () use ($candidate_id) { $current_member = $this->resource_server_context->getCurrentUser(); diff --git a/app/Swagger/CandidatesListSchema.php b/app/Swagger/CandidatesListSchema.php new file mode 100644 index 000000000..c3ee6dc33 --- /dev/null +++ b/app/Swagger/CandidatesListSchema.php @@ -0,0 +1,32 @@ + 'Read All Elections', + ElectionScopes::WriteMyCandidateProfile => 'Write My Candidate Profile', + ElectionScopes::NominatesCandidates => 'Nominate Candidates', + ], + ), + ], + ) +] +class ElectionOAuth2Security {} From 1857aba346733aae0a1e6e3fdb6bc3acb626d998 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Mon, 8 Dec 2025 15:59:46 +0000 Subject: [PATCH 2/3] chore: move security schema to app/Swagger/Security/ folder --- .../ElectionOAuth2SecuritySchema.php} | 2 +- .../SummitBookableRoomsAttributeTypeSecurity.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) rename app/Swagger/{security/ElectionOAuth2Schema.php => Security/ElectionOAuth2SecuritySchema.php} (95%) rename app/Swagger/{security => Security}/SummitBookableRoomsAttributeTypeSecurity.php (95%) diff --git a/app/Swagger/security/ElectionOAuth2Schema.php b/app/Swagger/Security/ElectionOAuth2SecuritySchema.php similarity index 95% rename from app/Swagger/security/ElectionOAuth2Schema.php rename to app/Swagger/Security/ElectionOAuth2SecuritySchema.php index c1a0fdfe2..25fe41221 100644 --- a/app/Swagger/security/ElectionOAuth2Schema.php +++ b/app/Swagger/Security/ElectionOAuth2SecuritySchema.php @@ -23,4 +23,4 @@ ], ) ] -class ElectionOAuth2Security {} +class ElectionOAuth2SecuritySchema {} diff --git a/app/Swagger/security/SummitBookableRoomsAttributeTypeSecurity.php b/app/Swagger/Security/SummitBookableRoomsAttributeTypeSecurity.php similarity index 95% rename from app/Swagger/security/SummitBookableRoomsAttributeTypeSecurity.php rename to app/Swagger/Security/SummitBookableRoomsAttributeTypeSecurity.php index 8b3ad5e8c..18238d0da 100644 --- a/app/Swagger/security/SummitBookableRoomsAttributeTypeSecurity.php +++ b/app/Swagger/Security/SummitBookableRoomsAttributeTypeSecurity.php @@ -1,11 +1,10 @@ - Date: Mon, 8 Dec 2025 16:17:43 +0000 Subject: [PATCH 3/3] fix: incorrect routes in path parameter and incorrect files names and refs --- .../Main/OAuth2ElectionsApiController.php | 20 +++--- app/Swagger/CandidatesListSchema.php | 32 ---------- app/Swagger/ElectionSchemas.php | 61 +++++++++++-------- .../{models => Models}/CandidateSchema.php | 0 .../{models => Models}/ElectionSchema.php | 0 ...itySchema.php => ElectionOAuth2Schema.php} | 2 +- 6 files changed, 47 insertions(+), 68 deletions(-) delete mode 100644 app/Swagger/CandidatesListSchema.php rename app/Swagger/{models => Models}/CandidateSchema.php (100%) rename app/Swagger/{models => Models}/ElectionSchema.php (100%) rename app/Swagger/Security/{ElectionOAuth2SecuritySchema.php => ElectionOAuth2Schema.php} (95%) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php index 7b3d0cf1e..ed79dcd04 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php @@ -93,14 +93,14 @@ public function __construct in: "query", required: false, schema: new OA\Schema(type: "string"), - description: "Expand relationships" + description: "Expand relationships: " ), ], responses: [ new OA\Response( response: Response::HTTP_OK, description: "Elections list retrieved successfully", - content: new OA\JsonContent(ref: "#/components/schemas/ElectionsList") + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedElectionsResponse") ), new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), @@ -152,7 +152,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) { } #[OA\Get( - path: "/api/v1/elections/current", + path: "/api/public/v1/elections/current", operationId: "getCurrentElection", description: "Get the current active election", tags: ["Elections (Public)"], @@ -252,7 +252,7 @@ public function getById($election_id) } #[OA\Get( - path: "/api/v1/elections/current/candidates", + path: "/api/public/v1/elections/current/candidates", operationId: "getCurrentElectionCandidates", description: "Get all accepted candidates for the current election. Supports expand parameter to include member and/or election objects", tags: ["Elections (Public)"], @@ -297,7 +297,7 @@ public function getById($election_id) new OA\Response( response: Response::HTTP_OK, description: "Current election candidates retrieved successfully", - content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedCandidatesResponse") ), new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), @@ -405,7 +405,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) new OA\Response( response: Response::HTTP_OK, description: "Election candidates retrieved successfully", - content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedCandidatesResponse") ), new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Election not found"), new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), @@ -460,7 +460,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) } #[OA\Get( - path: "/api/v1/elections/current/candidates/gold", + path: "/api/public/v1/elections/current/candidates/gold", operationId: "getCurrentGoldCandidates", description: "Get all gold (featured) candidates for the current election. Supports expand parameter to include member and/or election objects", tags: ["Elections (Public)"], @@ -505,7 +505,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) new OA\Response( response: Response::HTTP_OK, description: "Gold candidates retrieved successfully", - content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedCandidatesResponse") ), new OA\Response(response: Response::HTTP_NOT_FOUND, description: "No current election found"), new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), @@ -613,7 +613,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($election) new OA\Response( response: Response::HTTP_OK, description: "Gold candidates retrieved successfully", - content: new OA\JsonContent(ref: "#/components/schemas/CandidatesList") + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedCandidatesResponse") ), new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Election not found"), new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), @@ -791,4 +791,4 @@ public function nominateCandidate(int $candidate_id) }); } -} \ No newline at end of file +} diff --git a/app/Swagger/CandidatesListSchema.php b/app/Swagger/CandidatesListSchema.php deleted file mode 100644 index c3ee6dc33..000000000 --- a/app/Swagger/CandidatesListSchema.php +++ /dev/null @@ -1,32 +0,0 @@ -