From 93772ed1bb62e8b5c52814966646bb16abd4e1b1 Mon Sep 17 00:00:00 2001 From: smarcet Date: Tue, 30 Sep 2025 13:28:05 -0300 Subject: [PATCH 1/8] chore: refactor DoctrineSummitEventRepository to suppport 2 phase paging chore: fix .gitmessage.txt chore: increase header size to 150 --- .../Summit/DoctrineSummitAttendeeTicketRepository.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php index 9629a92fd..dcf9c04f0 100644 --- a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php +++ b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php @@ -745,6 +745,7 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord $start = time(); Log::debug(sprintf('DoctrineSummitAttendeeTicketRepository::getAllByPage')); $total = $this->getFastCount($filter, $order); + if(!$total) return new PagingResponse(0, $paging_info->getPerPage(), $paging_info->getCurrentPage(), 0, []); $ids = $this->getAllIdsByPage($paging_info, $filter, $order); $query = $this->getEntityManager()->createQueryBuilder() ->select('e, a, o, tt, pc, b, bt, a_c, m') @@ -764,6 +765,10 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord $byId = []; foreach ($rows as $e) $byId[$e->getId()] = $e; + $rows = $query->getQuery()->getResult(); + $byId = []; + foreach ($rows as $e) $byId[$e->getId()] = $e; + $data = []; foreach ($ids as $id) { if (isset($byId[$id])) $data[] = $byId[$id]; From 7f577a76cec60a50ae64be4c3b22a4938b453d05 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Tue, 30 Sep 2025 17:08:08 -0300 Subject: [PATCH 2/8] feat: Add OpenAPI documentation to "getAll" method - Add controller's response to OpenAPI schema --- .../Main/OAuth2AuditLogController.php | 76 ++++++++++++++++++- app/Swagger/schemas.php | 36 +++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php index c01041a90..fdd52d383 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php @@ -13,12 +13,15 @@ **/ use App\Models\Foundation\Main\Repositories\IAuditLogRepository; +use App\Security\SummitScopes; +use Illuminate\Http\Response; use models\main\SummitAttendeeBadgeAuditLog; use models\main\SummitAuditLog; use models\main\SummitEventAuditLog; use models\oauth2\IResourceServerContext; use models\summit\SummitAttendeeBadge; use ModelSerializers\SerializerRegistry; +use OpenApi\Attributes as OA; /** * Class OAuth2AuditLogController @@ -46,6 +49,77 @@ public function __construct /** * @return mixed */ + #[OA\Get( + path: "/api/v1/audit-logs", + description: "Get all audit logs with filtering capabilities. Requires OAuth2 authentication with appropriate scope.", + summary: 'Get all audit logs', + operationId: 'getAllAuditLogs', + tags: ['Audit Logs'], + security: [['summit_rsvp_oauth2' => [ + SummitScopes::ReadAllSummitData, + ]]], + parameters: [ + new OA\Parameter( + name: 'access_token', + in: 'query', + required: false, + description: 'OAuth2 access token (alternative to Authorization: Bearer)', + schema: new OA\Schema(type: 'string', example: 'eyJhbGciOi...') + ), + new OA\Parameter( + name: 'page', + in: 'query', + required: false, + description: 'Page number for pagination', + schema: new OA\Schema(type: 'integer', example: 1) + ), + new OA\Parameter( + name: 'per_page', + in: 'query', + required: false, + description: 'Items per page', + schema: new OA\Schema(type: 'integer', example: 10, maximum: 100) + ), + new OA\Parameter( + name: 'filter[]', + in: 'query', + required: false, + description: 'Filter expressions. Format: fieldvalue. Available fields: class_name (required, ==), user_id (==), summit_id (==), event_id (==), entity_id (==), user_email (==, =@, @@), user_full_name (==, =@, @@), action (=@, @@), metadata (==, =@, @@), created (==, >, <, >=, <=, []). class_name must be one of: SummitAuditLog, SummitEventAuditLog, SummitAttendeeBadgeAuditLog', + style: 'form', + explode: true, + schema: new OA\Schema( + type: 'array', + items: new OA\Items(type: 'string', example: 'class_name==SummitAuditLog') + ) + ), + new OA\Parameter( + name: 'order', + in: 'query', + required: false, + description: 'Order by field(s). Available fields: id, user_id, event_id, entity_id, created, user_email, user_full_name, metadata. Use "-" prefix for descending order.', + schema: new OA\Schema(type: 'string', example: '-created') + ), + new OA\Parameter( + name: 'expand', + in: 'query', + required: false, + description: 'Comma-separated list of related resources to include. Available relations: user, summit', + schema: new OA\Schema(type: 'string', example: 'user,summit') + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Success - Returns paginated list of audit logs', + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedAuditLogsResponse') + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request - Invalid parameters"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized - Invalid or missing access token"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden - Insufficient permissions"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error - Missing required filters"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error") + ] + )] public function getAll(){ return $this->_getAll( @@ -97,4 +171,4 @@ function () { } ); } -} \ No newline at end of file +} diff --git a/app/Swagger/schemas.php b/app/Swagger/schemas.php index 1eff77226..2efec74c4 100644 --- a/app/Swagger/schemas.php +++ b/app/Swagger/schemas.php @@ -351,3 +351,39 @@ class RSVPUpdateRequestSchema_{ ] )] class RSVPAdminAddRequestSchema {} + +#[OA\Schema( + schema: 'AuditLog', + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1, description: 'Unique identifier'), + new OA\Property(property: 'created', type: 'integer', example: 1630500518, description: 'Creation timestamp (Unix epoch)'), + new OA\Property(property: 'last_edited', type: 'integer', example: 1630500518, description: 'Last modification timestamp (Unix epoch)'), + new OA\Property(property: 'class_name', type: 'string', example: 'SummitAuditLog', description: 'Audit log type: SummitAuditLog, SummitEventAuditLog, or SummitAttendeeBadgeAuditLog'), + new OA\Property(property: 'action', type: 'string', example: 'UPDATED', description: 'Action performed (e.g., CREATED, UPDATED, DELETED)'), + new OA\Property(property: 'metadata', type: 'string', example: 'Additional audit information', description: 'Metadata about the audit action', nullable: true), + new OA\Property(property: 'user_id', type: 'integer', example: 123, description: 'ID of the user who performed the action'), + new OA\Property(property: 'summit_id', type: 'integer', example: 45, description: 'Summit ID (for SummitAuditLog, SummitEventAuditLog, SummitAttendeeBadgeAuditLog)', nullable: true), + new OA\Property(property: 'event_id', type: 'integer', example: 789, description: 'Event ID (for SummitEventAuditLog)', nullable: true), + new OA\Property(property: 'attendee_badge_id', type: 'integer', example: 456, description: 'Attendee Badge ID (for SummitAttendeeBadgeAuditLog)', nullable: true), + ] +)] +class AuditLogSchema {} + +#[OA\Schema( + schema: 'PaginatedAuditLogsResponse', + allOf: [ + new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'), + new OA\Schema( + type: 'object', + properties: [ + new OA\Property( + property: 'data', + type: 'array', + items: new OA\Items(ref: '#/components/schemas/AuditLog') + ) + ] + ) + ] +)] +class PaginatedAuditLogsResponseSchema {} From 695bfa85b1764fa375230bf15e023718b8203a95 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Wed, 8 Oct 2025 12:20:30 -0300 Subject: [PATCH 3/8] chore: Move schemas to the proper schemas file --- app/Swagger/AuditSchemas.php | 36 +++++++++++++++++++++++++++++++++++- app/Swagger/schemas.php | 36 ------------------------------------ 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/app/Swagger/AuditSchemas.php b/app/Swagger/AuditSchemas.php index 6b3e2f895..b86a1def4 100644 --- a/app/Swagger/AuditSchemas.php +++ b/app/Swagger/AuditSchemas.php @@ -4,4 +4,38 @@ use OpenApi\Attributes as OA; -// +#[OA\Schema( + schema: 'AuditLog', + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1, description: 'Unique identifier'), + new OA\Property(property: 'created', type: 'integer', example: 1630500518, description: 'Creation timestamp (Unix epoch)'), + new OA\Property(property: 'last_edited', type: 'integer', example: 1630500518, description: 'Last modification timestamp (Unix epoch)'), + new OA\Property(property: 'class_name', type: 'string', example: 'SummitAuditLog', description: 'Audit log type: SummitAuditLog, SummitEventAuditLog, or SummitAttendeeBadgeAuditLog'), + new OA\Property(property: 'action', type: 'string', example: 'UPDATED', description: 'Action performed (e.g., CREATED, UPDATED, DELETED)'), + new OA\Property(property: 'metadata', type: 'string', example: 'Additional audit information', description: 'Metadata about the audit action', nullable: true), + new OA\Property(property: 'user_id', type: 'integer', example: 123, description: 'ID of the user who performed the action'), + new OA\Property(property: 'summit_id', type: 'integer', example: 45, description: 'Summit ID (for SummitAuditLog, SummitEventAuditLog, SummitAttendeeBadgeAuditLog)', nullable: true), + new OA\Property(property: 'event_id', type: 'integer', example: 789, description: 'Event ID (for SummitEventAuditLog)', nullable: true), + new OA\Property(property: 'attendee_badge_id', type: 'integer', example: 456, description: 'Attendee Badge ID (for SummitAttendeeBadgeAuditLog)', nullable: true), + ] +)] +class AuditLogSchema {} + +#[OA\Schema( + schema: 'PaginatedAuditLogsResponse', + allOf: [ + new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'), + new OA\Schema( + type: 'object', + properties: [ + new OA\Property( + property: 'data', + type: 'array', + items: new OA\Items(ref: '#/components/schemas/AuditLog') + ) + ] + ) + ] +)] +class PaginatedAuditLogsResponseSchema {} diff --git a/app/Swagger/schemas.php b/app/Swagger/schemas.php index 2efec74c4..1eff77226 100644 --- a/app/Swagger/schemas.php +++ b/app/Swagger/schemas.php @@ -351,39 +351,3 @@ class RSVPUpdateRequestSchema_{ ] )] class RSVPAdminAddRequestSchema {} - -#[OA\Schema( - schema: 'AuditLog', - type: 'object', - properties: [ - new OA\Property(property: 'id', type: 'integer', example: 1, description: 'Unique identifier'), - new OA\Property(property: 'created', type: 'integer', example: 1630500518, description: 'Creation timestamp (Unix epoch)'), - new OA\Property(property: 'last_edited', type: 'integer', example: 1630500518, description: 'Last modification timestamp (Unix epoch)'), - new OA\Property(property: 'class_name', type: 'string', example: 'SummitAuditLog', description: 'Audit log type: SummitAuditLog, SummitEventAuditLog, or SummitAttendeeBadgeAuditLog'), - new OA\Property(property: 'action', type: 'string', example: 'UPDATED', description: 'Action performed (e.g., CREATED, UPDATED, DELETED)'), - new OA\Property(property: 'metadata', type: 'string', example: 'Additional audit information', description: 'Metadata about the audit action', nullable: true), - new OA\Property(property: 'user_id', type: 'integer', example: 123, description: 'ID of the user who performed the action'), - new OA\Property(property: 'summit_id', type: 'integer', example: 45, description: 'Summit ID (for SummitAuditLog, SummitEventAuditLog, SummitAttendeeBadgeAuditLog)', nullable: true), - new OA\Property(property: 'event_id', type: 'integer', example: 789, description: 'Event ID (for SummitEventAuditLog)', nullable: true), - new OA\Property(property: 'attendee_badge_id', type: 'integer', example: 456, description: 'Attendee Badge ID (for SummitAttendeeBadgeAuditLog)', nullable: true), - ] -)] -class AuditLogSchema {} - -#[OA\Schema( - schema: 'PaginatedAuditLogsResponse', - allOf: [ - new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'), - new OA\Schema( - type: 'object', - properties: [ - new OA\Property( - property: 'data', - type: 'array', - items: new OA\Items(ref: '#/components/schemas/AuditLog') - ) - ] - ) - ] -)] -class PaginatedAuditLogsResponseSchema {} From 9d7f11fe1e19ecddce1f6ebdda83cb99d8cf1eae Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Tue, 14 Oct 2025 14:11:33 -0300 Subject: [PATCH 4/8] fix: conflicts issue with main --- .../Summit/DoctrineSummitAttendeeTicketRepository.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php index dcf9c04f0..9629a92fd 100644 --- a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php +++ b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php @@ -745,7 +745,6 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord $start = time(); Log::debug(sprintf('DoctrineSummitAttendeeTicketRepository::getAllByPage')); $total = $this->getFastCount($filter, $order); - if(!$total) return new PagingResponse(0, $paging_info->getPerPage(), $paging_info->getCurrentPage(), 0, []); $ids = $this->getAllIdsByPage($paging_info, $filter, $order); $query = $this->getEntityManager()->createQueryBuilder() ->select('e, a, o, tt, pc, b, bt, a_c, m') @@ -765,10 +764,6 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord $byId = []; foreach ($rows as $e) $byId[$e->getId()] = $e; - $rows = $query->getQuery()->getResult(); - $byId = []; - foreach ($rows as $e) $byId[$e->getId()] = $e; - $data = []; foreach ($ids as $id) { if (isset($byId[$id])) $data[] = $byId[$id]; From 9a6049630f6eadb8073b33ca282cc29dbb1137b2 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Tue, 14 Oct 2025 14:12:12 -0300 Subject: [PATCH 5/8] fix: Change "namespace" word positioning --- .../Apis/Protected/Main/OAuth2AuditLogController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php index fdd52d383..eeac93d0a 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php @@ -1,4 +1,7 @@ - Date: Fri, 7 Nov 2025 18:15:03 +0000 Subject: [PATCH 6/8] fix: security scope --- .../Apis/Protected/Main/OAuth2AuditLogController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php index eeac93d0a..13bc80401 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php @@ -58,8 +58,8 @@ public function __construct summary: 'Get all audit logs', operationId: 'getAllAuditLogs', tags: ['Audit Logs'], - security: [['summit_rsvp_oauth2' => [ - SummitScopes::ReadAllSummitData, + security: [['audit_logs_oauth2' => [ + SummitScopes::ReadAuditLogs, ]]], parameters: [ new OA\Parameter( From b22fc29d76e47813f372c9ef6982b46bb1827de4 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Tue, 11 Nov 2025 21:11:25 +0000 Subject: [PATCH 7/8] fix: Add security schema --- .../Protected/Main/OAuth2AuditLogController.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php index 13bc80401..bbde2a11d 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php @@ -26,6 +26,22 @@ use ModelSerializers\SerializerRegistry; use OpenApi\Attributes as OA; +#[OA\SecurityScheme( + type: 'oauth2', + securityScheme: 'audit_logs_oauth2', + flows: [ + new OA\Flow( + authorizationUrl: L5_SWAGGER_CONST_AUTH_URL, + tokenUrl: L5_SWAGGER_CONST_TOKEN_URL, + flow: 'authorizationCode', + scopes: [ + ], + ), + ], + ) +] +class AuditLogAuthSchema{} + /** * Class OAuth2AuditLogController * @package App\Http\Controllers From a27b6dc06494c8289b5693852952687264d875d0 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Thu, 13 Nov 2025 19:38:20 +0000 Subject: [PATCH 8/8] chore: Move the security schema for the controller to its own file --- .../Main/OAuth2AuditLogController.php | 16 ------------ app/Swagger/Security/AuditLogAuthSchema.php | 25 +++++++++++++++++++ 2 files changed, 25 insertions(+), 16 deletions(-) create mode 100644 app/Swagger/Security/AuditLogAuthSchema.php diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php index bbde2a11d..13bc80401 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2AuditLogController.php @@ -26,22 +26,6 @@ use ModelSerializers\SerializerRegistry; use OpenApi\Attributes as OA; -#[OA\SecurityScheme( - type: 'oauth2', - securityScheme: 'audit_logs_oauth2', - flows: [ - new OA\Flow( - authorizationUrl: L5_SWAGGER_CONST_AUTH_URL, - tokenUrl: L5_SWAGGER_CONST_TOKEN_URL, - flow: 'authorizationCode', - scopes: [ - ], - ), - ], - ) -] -class AuditLogAuthSchema{} - /** * Class OAuth2AuditLogController * @package App\Http\Controllers diff --git a/app/Swagger/Security/AuditLogAuthSchema.php b/app/Swagger/Security/AuditLogAuthSchema.php new file mode 100644 index 000000000..305ff9414 --- /dev/null +++ b/app/Swagger/Security/AuditLogAuthSchema.php @@ -0,0 +1,25 @@ +