ecamp / ecamp/ecamp3

Implement Hitobito event retrieval endpoints

Open
#10,386 15 comments 0 reactions 1 assignee Claimed by @eliaSchenker View on GitHub
Ready for implementation type: API
Dominant language
PHP
Stars
156
Forks
72
Avg merge
12h 43m
Merged PRs (30d)
203

Description

The following endpoints are added, which allow retrieving events from Hitobito. Only events that the user manages are returned (that the user is `Lagerleiter:in` of).

## List Events
```jsonc
// GET /api/hitobito//events

// Response
{
"_links": {},
"totalItems": 5,
"_embedded": {
"items": [
{
"_links": {},
"_embedded": {},
"id": 1234,
"name": "Test Lager",
"isImported": false // whether the event was already imported into eCamp
}
// ...
]
}
}
```

### Implementation
1. Retrieve / verify access token
- See https://github.com/ecamp/ecamp3/issues/10400
2. Retrieve events from the Hitobito API:
```
GET /api/events
?include=participation.roles
&filter[event][after_or_on][eq]=
&filter[participations.participant_id]=
&filter[participations.participant_type][eq]=Person
&fields[events]=name
&fields[event_participations]=event_id,active
&fields[event_roles]=participation_id,type
&page[size]=100
```
> The `fields[event_participations], fields[events]=name, fields[event_roles]=type` params limit the fields that are returned, only including the specified fields. By default all fields of participations, events and event_roles would be returned, which results in a larger response body.

Example Response:
```jsonc
{
"data": [
// event where the user does not have an active participation
{
"id": "1044",
"type": "events",
"attributes": {
"name": "Templager_"
},
"relationships": {
// ...
"participations": {
"data": []
}
// ...
}
},
// event where the user has an active participation
{
"id": "2064",
"type": "events",
"attributes": {
"name": "SoLa 2050"
},
"relationships": {
// ...
"participations": {
"data": [
{
"type": "event_participations",
"id": "14668"
},
{
"type": "event_participations",
"id": "14665"
}
]
}
// ...
}
},
],
"included": [
{
"id": "14668",
"type": "event_participations",
"relationships": {
"event": {
"meta": {
"included": false
}
},
"participant": {
"meta": {
"included": false
}
},
"roles": {
"data": [
{
"type": "event_roles",
"id": "17996"
}
]
}
}
},
{
"id": "17996",
"type": "event_roles",
"attributes": {
"type": "Event::Camp::Role::Leader"
},
"relationships": {
"participation": {
"meta": {
"included": false
}
}
}
}
],
"links": {
// ...
},
"meta": {}
}
```

3. Perform the following steps on the retrieved data
1. Retrieve all included participations (`attributes.active = true`) and where **one of** the corresponding roles has `attributes.type = "Event::Camp::Role::Leader | Event::Role::Leader | Event::Course::Role::Leader"`
2. Look up the corresponding event, add the event `id` and `attributes.name` to result array
4. For every event, check if there is a corresponding camp and mark `isImported` accordingly
5. Return all gathered events

> Implementation Note: Make sure that the role that identifies a user as a leader of an event (for MiData `Event::Camp::Role::Leader`) is configurable per different Hitobito provider, so that new supported instance (i.e. CeviDB) can be easily added in the future.

> Optimally we would directly query the event name / filter the role when calling the api, but this is seemingly unsupported by Hitobito.

> There is a filter option to directly remove participations with certain roles (`filter[participations.roles.type][eq]=...`). However this currently results in an error on the Hitobito-side, so the filtering is performed manually in extractEvents. See comments on this issue for more details.

## Get Event
```jsonc
// GET /api/hitobito//events/

// Response
{
"id": 1234,
"name": "Lumos + Iltis",
"motto": "Kartoffelbauer und Nudelkönigin",
"location": "Hardstrasse 201, 8005 Zürich",
"dates": [
{
"label": "Politsche Ausrichtung der TN",
"startAt": "2026-01-01T00:01:00+01:00",
"finishAt": "2026-12-31T23:59:00+01:00"
}
],
"isImported": false
}
```

### Implementation
1. Retrieve / verify access token
- See https://github.com/ecamp/ecamp3/issues/10400
2. Check that the user has access to the specified event
1. See https://github.com/ecamp/ecamp3/issues/10419
3. Retrieve the event from Hitobito
```
GET /api/events/?include=dates
```
Example Response:
```jsonc
{
"data": {
"id": "2611",
"type": "events",
"attributes": {
"group_ids": [
1503,
1517
],
"type": "Event::Camp",
"kind_id": null,
"name": "Lumos + Iltis",
"description": null,
"application_conditions": null,
"motto": "Kartoffelbauer und Nudelkönigin",
"cost": "190'000.00",
"location": "Hardstrasse 201, 8005 Zürich",
"application_opening_at": null,
"application_closing_at": null,
"application_contact_id": null,
"external_application_link": null,
"maximum_participants": null,
"created_at": "2025-08-06T16:05:38+02:00",
"updated_at": "2026-07-27T13:04:13+02:00",
"advisor_id": null
},
"relationships": {
// ...
"dates": {
"data": [
{
"type": "dates",
"id": "3739"
}
]
},
}
},
"included": [
{
"id": "3739",
"type": "dates",
"attributes": {
"event_id": 2611,
"label": "Politsche Ausrichtung der TN",
"location": "Zürich",
"start_at": "2026-01-01T00:01:00+01:00",
"finish_at": "2026-12-31T23:59:00+01:00"
},
"relationships": {
"event": {
"meta": {
"included": false
}
}
}
}
],
"meta": {}
}
```

4. Check if there is a corresponding camp and mark `isImported` accordingly
5. Respond with the event as specified above

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.