From 189390c8debbb4c26ca7977b6cc3ea0c5fbbb6bd Mon Sep 17 00:00:00 2001 From: Jose Andres Tejerina Date: Fri, 14 Nov 2025 15:12:33 -0300 Subject: [PATCH] feat: Add openapi documentation for OAuth2SummitBadgeScanApiController --- .../OAuth2SummitBadgeScanApiController.php | 320 ++++++++++++++++-- app/Swagger/SponsorBadgeScanSchemas.php | 145 ++++++++ .../security/SponsorBadgeScanAuthScheme.php | 32 ++ 3 files changed, 476 insertions(+), 21 deletions(-) create mode 100644 app/Swagger/SponsorBadgeScanSchemas.php create mode 100644 app/Swagger/security/SponsorBadgeScanAuthScheme.php diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php index 598d729b6..479be4b86 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeScanApiController.php @@ -14,6 +14,8 @@ use App\Http\Exceptions\HTTP403ForbiddenException; use App\Http\Utils\EpochCellFormatter; use App\ModelSerializers\SerializerUtils; +use App\Models\Foundation\Main\IGroup; +use App\Security\SummitScopes; use App\Services\Model\IAttendeeService; use Illuminate\Support\Facades\Request; use Libs\ModelSerializers\AbstractSerializer; @@ -28,6 +30,8 @@ use models\summit\SummitOrderExtraQuestionTypeConstants; use models\utils\IEntity; use ModelSerializers\SerializerRegistry; +use OpenApi\Attributes as OA; +use Symfony\Component\HttpFoundation\Response; use utils\Filter; use utils\FilterElement; /** @@ -146,11 +150,31 @@ protected function updateChild(Summit $summit,int $child_id, array $payload):IEn return $this->service->updateBadgeScan($summit, $current_member, $child_id, $payload); } - /** - * @param $summit_id - * @param $sponsor_id - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Post( + path: "/api/v1/summits/{id}/sponsors/{sponsor_id}/user-info-grants/me", + summary: "Add user info grant for current user", + operationId: "addUserInfoWithSponsor", + tags: ["SponsorUserInfoGrants"], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::WriteMyBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "sponsor_id", description: "Sponsor ID", in: "path", required: true, schema: new OA\Schema(type: "integer")), + ], + responses: [ + new OA\Response( + response: Response::HTTP_CREATED, + description: "Created", + content: new OA\JsonContent(ref: "#/components/schemas/SponsorUserInfoGrant") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function addGrant($summit_id, $sponsor_id){ return $this->processRequest(function() use($summit_id, $sponsor_id){ $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); @@ -183,10 +207,34 @@ protected function getSummitRepository(): ISummitRepository // traits use ParametrizedGetAll; - /** - * @param $summit_id - * @return \Illuminate\Http\JsonResponse|mixed - */ + #[OA\Get( + path: "/api/v1/summits/{id}/badge-scans/me", + summary: "Get all my badge scans for a summit", + operationId: "getMyBadgeScans", + tags: ['BadgeScans'], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::ReadMyBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "page", description: "Page number", in: "query", required: false, schema: new OA\Schema(type: "integer", default: 1)), + new OA\Parameter(name: "per_page", description: "Items per page", in: "query", required: false, schema: new OA\Schema(type: "integer", default: 10)), + new OA\Parameter(name: "filter", description: "Filter query", in: "query", required: false, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "order", description: "Order by", in: "query", required: false, schema: new OA\Schema(type: "string")), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "OK", + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedBadgeScansResponse") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getAllMyBadgeScans($summit_id){ $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id); if (is_null($summit)) @@ -238,10 +286,44 @@ function(){ ); } - /** - * @param $summit_id - * @return mixed - */ + #[OA\Get( + path: "/api/v1/summits/{id}/badge-scans", + summary: "Get all badge scans for a summit", + operationId: "getAllBadgeScans", + tags: ['BadgeScans'], + x: [ + 'required-groups' => [ + IGroup::SummitAdministrators, + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::Sponsors, + IGroup::SponsorExternalUsers, + ] + ], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::ReadAllSummitData, + SummitScopes::ReadBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "page", description: "Page number", in: "query", required: false, schema: new OA\Schema(type: "integer", default: 1)), + new OA\Parameter(name: "per_page", description: "Items per page", in: "query", required: false, schema: new OA\Schema(type: "integer", default: 10)), + new OA\Parameter(name: "filter", description: "Filter query", in: "query", required: false, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "order", description: "Order by", in: "query", required: false, schema: new OA\Schema(type: "string")), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "OK", + content: new OA\JsonContent(ref: "#/components/schemas/PaginatedBadgeScansResponse") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getAllBySummit($summit_id){ $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id); @@ -322,10 +404,46 @@ function(){ ); } - /** - * @param $summit_id - * @return mixed - */ + #[OA\Get( + path: "/api/v1/summits/{id}/badge-scans/csv", + summary: "Get all badge scans for a summit in CSV format", + operationId: "getAllBadgeScansCSV", + tags: ['BadgeScans'], + x: [ + 'required-groups' => [ + IGroup::SummitAdministrators, + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::Sponsors, + IGroup::SponsorExternalUsers, + ] + ], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::ReadAllSummitData, + SummitScopes::ReadBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "filter", description: "Filter query", in: "query", required: false, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "order", description: "Order by", in: "query", required: false, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "columns", description: "Columns to export (comma separated)", in: "query", required: false, schema: new OA\Schema(type: "string")), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "OK", + content: new OA\MediaType( + mediaType: "text/csv", + schema: new OA\Schema(type: "string", format: "binary") + ) + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] public function getAllBySummitCSV($summit_id){ $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id); @@ -457,10 +575,78 @@ function() use($summit) { ); } - /** - * @param $summit_id - * @return mixed - */ + #[OA\Post( + path: "/api/v1/summits/{id}/badge-scans", + summary: "Add a badge scan", + operationId: "addBadgeScan", + tags: ['BadgeScans'], + x: [ + 'required-groups' => [ + IGroup::SummitAdministrators, + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::Sponsors, + IGroup::SponsorExternalUsers, + ] + ], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::WriteBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: "#/components/schemas/BadgeScanAddRequest") + ), + responses: [ + new OA\Response( + response: Response::HTTP_CREATED, + description: "Created", + content: new OA\JsonContent(ref: "#/components/schemas/SponsorBadgeScan") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "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 add($summit_id){ + return $this->processRequest(function() use($summit_id){ + $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); + if (is_null($summit)) return $this->error404(); + return $this->_add($summit, $this->getJsonPayload($this->getAddValidationRules())); + }); + } + + #[OA\Put( + path: "/api/v1/summits/{id}/badge-scans/checkin", + summary: "Check in an attendee using QR code", + operationId: "checkInBadgeScan", + tags: ['BadgeScans'], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::WriteBadgeScan, + SummitScopes::WriteSummitData, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: "#/components/schemas/BadgeScanCheckInRequest") + ), + responses: [ + new OA\Response(response: Response::HTTP_OK, description: "OK"), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "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"), + ] + )] protected function checkIn($summit_id) { return $this->processRequest(function () use ($summit_id) { if(!Request::isJson()) return $this->error400(); @@ -488,4 +674,96 @@ protected function getChildFromSummit(Summit $summit, $child_id): ?IEntity return $this->service->getBadgeScan($summit, $current_member, $child_id); } + + #[OA\Get( + path: "/api/v1/summits/{id}/badge-scans/{scan_id}", + summary: "Get a badge scan by id", + operationId: "getBadgeScan", + tags: ['BadgeScans'], + x: [ + 'required-groups' => [ + IGroup::SummitAdministrators, + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::Sponsors, + IGroup::SponsorExternalUsers, + ] + ], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::ReadAllSummitData, + SummitScopes::ReadBadgeScan, + SummitScopes::ReadMyBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "scan_id", description: "Badge scan ID", in: "path", required: true, schema: new OA\Schema(type: "integer")), + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "OK", + content: new OA\JsonContent(ref: "#/components/schemas/SponsorBadgeScan") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "not found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + public function get($summit_id, $scan_id){ + return $this->processRequest(function() use($summit_id, $scan_id){ + $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); + if (is_null($summit)) return $this->error404(); + return $this->_get($summit, $scan_id); + }); + } + + #[OA\Put( + path: "/api/v1/summits/{id}/badge-scans/{scan_id}", + summary: "Update a badge scan", + operationId: "updateBadgeScan", + tags: ['BadgeScans'], + x: [ + 'required-groups' => [ + IGroup::SummitAdministrators, + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::Sponsors, + IGroup::SponsorExternalUsers, + ] + ], + security: [['summit_badge_scan_oauth2' => [ + SummitScopes::WriteSummitData, + SummitScopes::WriteBadgeScan, + ]]], + parameters: [ + new OA\Parameter(name: "id", description: "Summit ID or slug", in: "path", required: true, schema: new OA\Schema(type: "string")), + new OA\Parameter(name: "scan_id", description: "Badge scan ID", in: "path", required: true, schema: new OA\Schema(type: "integer")), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: "#/components/schemas/BadgeScanUpdateRequest") + ), + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: "OK", + content: new OA\JsonContent(ref: "#/components/schemas/SponsorBadgeScan") + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "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 update($summit_id, $scan_id){ + return $this->processRequest(function() use($summit_id, $scan_id){ + $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); + if (is_null($summit)) return $this->error404(); + return $this->_update($summit, $scan_id, $this->getJsonPayload($this->getUpdateValidationRules())); + }); + } } diff --git a/app/Swagger/SponsorBadgeScanSchemas.php b/app/Swagger/SponsorBadgeScanSchemas.php new file mode 100644 index 000000000..53d25498f --- /dev/null +++ b/app/Swagger/SponsorBadgeScanSchemas.php @@ -0,0 +1,145 @@ + 'Read Badge Scan Data', + SummitScopes::ReadMyBadgeScan => 'Read My Badge Scan Data', + SummitScopes::WriteBadgeScan => 'Write Badge Scan Data', + SummitScopes::ReadBadgeScanValidate => 'Validate Badge Scan', + SummitScopes::ReadAllSummitData => 'Read All Summit Data', + SummitScopes::WriteSummitData => 'Write Summit Data', + ], + ), + ], + ) +] +class SponsorBadgeScanAuthScheme +{ +}