diff --git a/.github/workflows/check-branch-name.yml b/.github/workflows/check-branch-name.yml index b4cb8f73d..c2059cf95 100644 --- a/.github/workflows/check-branch-name.yml +++ b/.github/workflows/check-branch-name.yml @@ -12,8 +12,8 @@ jobs: run: | BRANCH_NAME="${{ github.head_ref }}" echo "Checking branch name: $BRANCH_NAME" - if [[ ! "$BRANCH_NAME" =~ ^(chore|feature|fix|hotfix|patch|refactor)/[a-z0-9._-]+$ ]]; then + if [[ ! "$BRANCH_NAME" =~ ^(chore|feat|feature|fix|hotfix|patch|refactor)/[a-z0-9._-]+$ ]]; then echo "❌ Invalid branch name: $BRANCH_NAME" echo "✅ Should match: feature/foo-bar, hotfix/issue-123, etc." exit 1 - fi \ No newline at end of file + fi diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitApiController.php index 40d1fdc28..d552bc377 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitApiController.php @@ -2554,7 +2554,7 @@ public function validateBadge($summit_id, $badge) { return $this->ok(SerializerRegistry::getInstance() ->getSerializer($summitAttendeeBadge) ->serialize( - 'features,ticket,ticket.owner,ticket.owner', + 'features,ticket,ticket.owner,ticket.owner,ticket.owner.member', [ 'id', 'features.id', @@ -2562,10 +2562,15 @@ public function validateBadge($summit_id, $badge) { 'features.description', 'ticket.id', 'ticket.number', + 'ticket.owner.id', 'ticket.owner.first_name', 'ticket.owner.last_name', 'ticket.owner.email', 'ticket.owner.company', + 'ticket.owner.member.id', + 'ticket.owner.member.first_name', + 'ticket.owner.member.last_name', + 'ticket.owner.member.pic', ] ) ); diff --git a/tests/InsertSummitTestData.php b/tests/InsertSummitTestData.php index 640e195c4..d364ccf0e 100644 --- a/tests/InsertSummitTestData.php +++ b/tests/InsertSummitTestData.php @@ -530,6 +530,37 @@ protected static function insertSummitTestData(){ $ticket->generateQRCode(); $summitAttendeeBadge->generateQRCode(); } + + // Member-less attendee (SummitAttendee.member is null) with a badge, so the + // validateBadge member-less path (D26/D27) has fixture coverage. Looked up in tests + // via Summit::getAttendeeByEmailAndMemberNotSet('memberless@test.com'). + $memberless_attendee = new SummitAttendee(); + $memberless_attendee->setEmail("memberless@test.com"); + $memberless_attendee->setFirstName("No"); + $memberless_attendee->setSurname("Member"); + + $memberless_badge = new SummitAttendeeBadge(); + $memberless_badge->setType(self::$default_badge_type); + + $memberless_order = new SummitOrder(); + $memberless_order->setOwner(self::$defaultMember); + $memberless_order->setSummit(self::$summit); + + $memberless_ticket = new SummitAttendeeTicket(); + $memberless_ticket->setTicketType(self::$default_ticket_type); + $memberless_ticket->setBadge($memberless_badge); + $memberless_ticket->activate(); + $memberless_attendee->addTicket($memberless_ticket); + $memberless_order->addTicket($memberless_ticket); + + self::$summit->addAttendee($memberless_attendee); + self::$summit->addOrder($memberless_order); + + $memberless_order->setPaid(); + $memberless_order->generateNumber(); + $memberless_ticket->generateNumber(); + $memberless_ticket->generateQRCode(); + $memberless_badge->generateQRCode(); } if (self::$defaultMember2 != null) { diff --git a/tests/oauth2/OAuth2SummitApiTest.php b/tests/oauth2/OAuth2SummitApiTest.php index f2dc68610..9469ec79d 100644 --- a/tests/oauth2/OAuth2SummitApiTest.php +++ b/tests/oauth2/OAuth2SummitApiTest.php @@ -1197,19 +1197,48 @@ public function testUpdateSummitRegSlugPrefixHavingPaidTickets(){ $this->assertStringContainsString('there are paid tickets', $content); } + // #40 / D26 augmentation regression: the badge-resolve payload must expose the attendee id + // (keys the D27 pre-account request) plus the expanded nested member snapshot (the D15 identity + // + name/photo) for member-linked attendees, and must OMIT the member object for member-less + // ones. Locks the serializer whitelist so the networking-api connect resolve does not regress. + public function testValidateBadge(){ + // MEMBER case: a member-linked attendee resolves with the expanded member object. + $owner = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($owner); + $member = $owner->getMember(); + + $attendee_badge = $this->callValidateBadge($owner->getFirstTicket()->getBadge()); + + // attendee id present (D27 keys the pre-account request on it) + $this->assertEquals($owner->getId(), $attendee_badge->ticket->owner->id); + + // owner.member is the EXPANDED object carrying the D15 identity + name/photo snapshot + $this->assertNotNull($attendee_badge->ticket->owner->member); + $this->assertEquals($member->getId(), $attendee_badge->ticket->owner->member->id); + $this->assertTrue(isset($attendee_badge->ticket->owner->member->first_name)); + } + + public function testValidateBadgeMemberLess(){ + // MEMBER-LESS case (D27): the fixture's member-less attendee resolves with NO member object. + $owner = self::$summit->getAttendeeByEmailAndMemberNotSet("memberless@test.com"); + $this->assertNotNull($owner); + $this->assertFalse($owner->hasMember()); - $badge_repository = EntityManager::getRepository(SummitAttendeeBadge::class); - $ticket = self::$summit_orders[0]->getTickets()->first(); - $badge = $badge_repository->getBadgeByTicketNumber($ticket->getNumber()); - $badge_qr_code = $badge->generateQRCode(); + $attendee_badge = $this->callValidateBadge($owner->getFirstTicket()->getBadge()); - //$key = '35NVOF4I5T6AAM28IJPKB8KRUW98KPDO'; + // attendee id + email are present (they key the pre-account request and address the email) + $this->assertEquals($owner->getId(), $attendee_badge->ticket->owner->id); + $this->assertTrue(isset($attendee_badge->ticket->owner->email)); + // no linked member => the expanded member object must be ABSENT + $this->assertFalse(isset($attendee_badge->ticket->owner->member)); + } + + private function callValidateBadge(SummitAttendeeBadge $badge) { $params = [ - 'id' => self::$summit->getId(), - //'badge' => base64_encode(AES::encrypt($key, $badge_qr_code)), - 'badge' => base64_encode($badge_qr_code), + 'id' => self::$summit->getId(), + 'badge' => base64_encode($badge->generateQRCode()), ]; $response = $this->action( @@ -1223,8 +1252,9 @@ public function testValidateBadge(){ ); $this->assertResponseStatus(200); - $content = $response->getContent(); - $attendee_badge = json_decode($content); + $attendee_badge = json_decode($response->getContent()); $this->assertNotNull($attendee_badge); + return $attendee_badge; } + }