Skip to content

Tags: OpenStackweb/summit-api

Tags

v4.0.39

Toggle v4.0.39's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
fix: dispatch original entity id in DeletedEventDTO, not a post-flush…

… getId() (#575)

Doctrine nulls an entity's identifier field via reflection after a hard
delete is flushed (UnitOfWork::executeDeletions). DeletedEventDTO::fromEntity()
was being called after the owning transaction closed, so it read that
stale, zeroed id and dispatched 'id' => 0 in the domain event payload.

Added DeletedEventDTO::fromId() and switched the affected dispatch call
sites to build the DTO from the id captured before removal:

- SummitSponsorshipService::removeSponsorship / removeAddOn
- SummitSponsorService::deleteSponsor
- SummitMediaFileTypeService::delete

Also applied the same fromId() call in SummitService::deleteSummit for
consistency, though that path only flips a soft-delete flag (no
em->remove()), so it never actually reproduced the zeroed-id bug.

Added regression tests for all four dispatch paths, verified against the
pre-fix code to confirm they fail with the original id => 0 defect
(SummitService's stays green either way, per the note above).

v4.0.38

Toggle v4.0.38's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
fix: prevent TypeError when renaming a SummitMediaFileType to a new u…

…nique name

SummitMediaFileTypeService::update() reused the $type variable for a
name-uniqueness check, overwriting the entity fetched via getById($id).
When the payload's new name did not already exist in the DB, getByName()
returned null, clobbering $type and causing
SummitMediaFileTypeFactory::populate() to blow up with:

  TypeError: populate(): Argument #1 ($type) must be of type
  models\summit\SummitMediaFileType, null given

The uniqueness check now uses its own $existing_type variable instead of
overwriting the entity being updated.

v4.0.37

Toggle v4.0.37's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
fix: prevent TypeError when renaming a SummitMediaFileType to a new u…

…nique name

SummitMediaFileTypeService::update() reused the $type variable for a
name-uniqueness check, overwriting the entity fetched via getById($id).
When the payload's new name did not already exist in the DB, getByName()
returned null, clobbering $type and causing
SummitMediaFileTypeFactory::populate() to blow up with:

  TypeError: populate(): Argument #1 ($type) must be of type
  models\summit\SummitMediaFileType, null given

The uniqueness check now uses its own $existing_type variable instead of
overwriting the entity being updated.

v4.0.36

Toggle v4.0.36's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
fix: don't force ENGINE=MEMORY on speaker/member activity count temp …

…tables

Production MySQL (hardened/managed instances, e.g. DigitalOcean) disables
the MEMORY storage engine, so CREATE TEMPORARY TABLE ... ENGINE=MEMORY
fails with SQLSTATE[HY000]: 3161 "Storage engine MEMORY is disabled".
This broke DoctrineSpeakerRepository::getUniqueActivitiesCountBySummit
(getSpeakersActivitiesCount endpoint) and the identical pattern in
DoctrineMemberRepository::getUniqueActivitiesCountBySummit.

Drop the explicit ENGINE=MEMORY clause so the temp tables use the
server's default engine (InnoDB), which isn't disabled.

Added regression tests that capture the emitted DDL via MySQL's general
query log and assert ENGINE=MEMORY is never present, since
disabled_storage_engines itself is a restart-only sysvar and can't be
toggled live in a test.

v4.0.35

Toggle v4.0.35's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Hotfix/attendee regenerate qr code (#572)

* fix: remap local docker-compose host ports to avoid conflicts with sibling stacks

otel-collector, elasticsearch, and rabbitmq_sponsor_services published the same host ports as openstackid's and purchases-api's local stacks (9200/9300, 1888/8888/8889/13133/4317/4318/55679, 5672/15672), which broke docker compose up when multiple FN local stacks ran side by side. Container-internal ports are unchanged; only host-side mappings moved.

* fix(badges): generate-on-read + reassignment QR staleness (ClickUp 86baxuvj3)

GET /summits/{id}/attendees/me?expand=tickets.badge now regenerates the
caller's badge QR code on every read (AttendeeService::regenerateAttendeeBadgesQRCodes),
so "My QR" renders even for never-printed badges.

Fixes badge QR staleness on ticket reassignment across all three writers:
AttendeeService::reassignAttendeeTicket, reassignAttendeeTicketByMember, and
SummitOrderService::updateTicket. A ticket fetched via an exclusive lock does
not populate Doctrine's inverse-side badge association, so hasBadge()/getBadge()
are unreliable afterward - resolved via a shared ResolvesLockedTicketBadge trait
that looks the badge up independently by ticket number and re-attaches it.

Also fixes a latent duplicate-badge-row risk in updateTicket's badge_type_id
branch, and adds try/catch guards around badge generation so one bad badge
(broken legacy ticket/order/summit chain) can't 500 an otherwise-successful
read or abort the rest of a generation batch.

Resolves fntechgit/ftn-docsnsklz#70.

* fix(badges): remove unnecessary ResolvesLockedTicketBadge workaround

The previous commit shipped a trait working around a claimed Doctrine
behavior ("exclusive-lock fetch doesn't populate inverse-side to-one
associations") that does not actually exist. Verified with isolated,
instrumented tests (SQL capture, object-identity checks, UnitOfWork
state checks): $ticket->hasBadge()/getBadge() work correctly on a
ticket fetched via getByIdExclusiveLock(), with no workaround needed.

The earlier misleading result was caused by two unrelated confounds in
diagnostic testing: mixing two different EntityManager instances (the
LaravelDoctrine facade vs a test fixture's own self::$em), and a
pre-existing test fixture bug (InsertSummitTestData reuses one
SummitAttendeeBadge object across 5 tickets, so attendee->getTickets()
->first() is not reliably the ticket that badge's DB row points to).

Reverts all four call sites (AttendeeService::reassignAttendeeTicket,
reassignAttendeeTicketByMember, and both branches of
SummitOrderService::updateTicket) to plain hasBadge()/getBadge().
Keeps the try/catch guard around generateQRCode(), which is unrelated
and still valid. Deletes the ResolvesLockedTicketBadge trait.

Full targeted suite re-verified: 45/46 pass (same pre-existing,
unrelated failure as before).

* fix(badges): only regenerate badge QR when tickets.badge is expanded

Per CodeRabbit review on PR #572 (discussion_r3587418919): getOwnAttendee
was invoking regenerateAttendeeBadgesQRCodes() unconditionally, exclusively
locking and regenerating every active badge even on requests that never
expand tickets.badge and therefore never serialize badge data at all.

Now only calls it when 'tickets.badge' is present in the expand param.
Keeps the always-regenerate behavior (no skip-if-already-has-QR) per
explicit prior decision - this only scopes *when* it runs, not whether
existing QR codes are trusted.

Added testGetOwnAttendeeDoesNotGenerateBadgeQRCodeWhenBadgeNotExpanded,
verified RED (failed against the unconditional call) before GREEN.
Full targeted suite re-verified: 46/47 pass (same pre-existing failure).

* docs(badges): fix typo in getOwnAttendee swagger description

Per PR #572 review (discussion_r3587772934, @romanetar): "que" was a
Spanish word leaked into the English OpenAPI description. Also updated
the wording to reflect the actual current behavior (regeneration only
happens when tickets.badge is expanded).

v4.0.34

Toggle v4.0.34's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
feature (registration): add order extra question answers to ticket CS…

…V import (#567)

* feat(registration): add order extra question answers to ticket CSV import

Adds extra_question:{question name} column support to the ticket data
import, template endpoint and OpenAPI docs. Answers are upserted through
the existing ExtraQuestionAnswerHolder persistence path; unknown
questions, order-scoped questions, disallowed questions, empty values
and locked answers are logged and skipped without failing the row.
List type questions accept value name/label/id ('|' separated for
CheckBoxList) and store value ids.

Co-Authored-By: Claude Fable 5 <[email protected]>

* test(registration): fix badge-features import test fixture assumptions

The import re-reads tickets with HINT_REFRESH, so it sees DB state: the
fixture's assigned tickets share one badge entity whose FK points at only
the last of them. Use an unassigned ticket, which gets its own
DB-consistent badge from SummitTicketType::applyTo.

Co-Authored-By: Claude Fable 5 <[email protected]>

* fix(registration): normalize list answer ordering + guard import row on answer persistence

Per CodeRabbit review: sort list-question value ids so the same selection
in a different order is not treated as a changed answer, and catch
ValidationException from the extra-question persistence path so one bad
payload cannot strand the remaining import rows.

Co-Authored-By: Claude Fable 5 <[email protected]>

* refactor(registration): review fixes for extra-question CSV import

Per review: process badge data before extra questions and flush + evict
the badge-features result cache so same-row badge/feature grants are
visible to the question permission gates; split the upsert into
resolve/merge helpers; ctype_digit for raw value ids; targeted cache
forget in tests. Adds regression tests for the same-row feature grant
(new + existing attendee), order-scoped skip, locked-answer skip, and
badge creation for badge-less tickets (folds in #568).

Co-Authored-By: Claude Fable 5 <[email protected]>

* test(registration): badge-less ticket requires a summit without a default badge type

SummitTicketType::getBadgeType falls back to the summit default badge
type, so on the main fixture summit applyTo always builds a badge and a
badge-less ticket cannot be constructed. Build the scenario on the second
fixture summit, which has no badge types — the real case the badge
creation fix covers.

Co-Authored-By: Claude Fable 5 <[email protected]>

* test(registration): set support email on summit2 fixture path

SummitAttendeeTicketEmail's constructor requires the summit support
email; the second fixture summit never sets one, so the ticket
reassignment path threw during the badge-less import test.

Co-Authored-By: Claude Fable 5 <[email protected]>

* fix(registration): dedupe resolved list-question value ids on ticket import

Duplicated CSV tokens (drag-fill artifacts, or the same choice spelled
as name/label/raw id) resolve to the same value id: they falsely
tripped the single-value guard on radio/combo questions and persisted
duplicated id strings for CheckBoxList, which also resisted later
correction under the answer-change lock. Adds both regression tests
from review.

Co-Authored-By: Claude Fable 5 <[email protected]>

---------

Co-authored-by: Claude Fable 5 <[email protected]>

v4.0.33

Toggle v4.0.33's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
feat: add execution time logging to doIntrospectionRequest

v4.0.32

Toggle v4.0.32's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(members): stop stale access-token group claim from stripping out-…

…of-band groups (#553)

* fix(members): stop stale access-token group claim from stripping out-of-band groups

getCurrentUser() ran synchronizeGroups() on every request using the access-token
user_groups claim, a snapshot taken at token issuance. That path removed any group
not present in the (stale) claim and not in a hardcoded skip-list, so a group added
out-of-band after login (e.g. sponsors-services added via the PublishUserUpdated
webhook) was re-stripped by the next /members/me request reusing the old token.

- synchronizeGroups() gains $allow_removals (default true); the per-request path
  (ResourceServerContext::checkGroups) now passes false, making it additive-only.
  Removals remain on the authoritative live-IDP webhook path only.
- Fix the throttle cache: GET read a per-group key while SET wrote a key without the
  group list, so it never hit and the add/remove logic ran on every request. Keys are
  now unified (sorted, mode-tagged).
- Add MemberServiceTest regression coverage for both additive and full-sync modes.

* fix(members): hash group-set in sync throttle key to avoid collisions

Addresses CodeRabbit PR #553: an underscore-joined group list is ambiguous
(["a_b","c"] and ["a","b_c"] collide), which could wrongly short-circuit a
sync for the wrong group set for the TTL window. Fingerprint the sorted set
with sha1(json_encode()) instead.

v4.0.31

Toggle v4.0.31's commit message

Verified

This commit was signed with the committer’s verified signature.
smarcet sebastian marcet
fix(tests): correct IStorageTypesConstants namespace in PresentationS…

…erviceMediaUploadTest

Class lives at App\Models\Utils\IStorageTypesConstants, not models\summit.

v4.0.30

Toggle v4.0.30's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(promo-codes): preserve ticket_types_rules on discount code update (

…#552)

A discount code PUT echoes back the whole serialized object, so the
payload carries the leftover top-level amount/rate alongside
ticket_types_rules. SummitPromoCodeFactory::populate applied
setAmount()/setRate(), which clear the ticket_types_rules collection
(orphanRemoval) and deleted the existing rules on update. Ignore the
top-level amount/rate when ticket_types_rules are present so the
per-ticket-type rules survive.

- factory: skip amount/rate when ticket_types_rules present
- add SummitPromoCodeFactoryTest for the regression and flat-rate path
- remove stale DomainAuthorizedPromoCodeTest cases asserting the
  addTicketTypeRule/removeTicketTypeRule overrides deleted in 497839b;
  sync SDS Truth #4 and design notes
- ci(push.yml): pass tests/Unit/Services and tests/Repositories
  positionally (were given to --filter, matching zero tests)