-
Notifications
You must be signed in to change notification settings - Fork 0
Backend
Joël Deffner edited this page Jul 17, 2026
·
1 revision
The backend is a CodeIgniter 4.7 application (PHP 8.2) in app/. It is a JSON-only API: every controller returns $this->response->setJSON(...), never HTML. Authentication is handled by CodeIgniter Shield (session-based), the database is MariaDB.
All routes live in app/Config/Routes.php, entirely inside one api group. Summary (full request/response shapes in API Reference):
| Area | Routes | Auth |
|---|---|---|
| Utility |
GET api/ping, POST api/echo
|
public |
| Weather |
GET api/weather, GET api/weather/reports, POST api/weather/reports/{id}/refresh
|
public |
| Activity | GET api/activity |
public |
| Pilot profiles | GET api/users/{username} |
public |
| Auth |
api/auth/me, register, login, logout
|
public/guest |
| Meets | list/detail/weather public; create/update/join/leave |
apiauth filter on mutations |
| Groups | list/detail public; create/update/join/leave |
apiauth filter on mutations |
| Chat |
api/chat/messages (GET/POST/DELETE) |
apiauth (whole group) |
| Own profile |
api/profile (GET/PUT), api/profile/subscription (PUT) |
apiauth |
| Admin |
api/admin/users CRUD |
adminapi filter |
| Controller | Responsibility |
|---|---|
Api.php |
Smoke-test endpoints: ping and echo. |
Weather.php |
Open-Meteo proxy: city search + forecast, cached weather reports, refresh. See Weather Integration. |
Api/AuthController.php |
Session login/logout, me (session status + CSRF token), and registration. Registration creates a Shield account in group user, logs the session in, and returns the same { user, csrf } shape as login. |
Api/MeetsController.php |
The meets domain: list, detail, create (with geocoding fallback), edit (creator or admin only), join/leave with full/duplicate conflict handling, and per-meet weather. |
Api/GroupsController.php |
Flight groups: list, detail, create (creator auto-joins), edit (founder or admin only), join/leave. |
Api/ChatController.php |
Global and per-group chat: incremental listing (after cursor), sending, and deleting (author or admin). Group channels require membership. |
Api/ProfileController.php |
The logged-in user's own profile: view, update (no group/active/tier changes here), and subscription tier switching (pilot / club / school, no payment flow, switching is free). |
Api/UsersController.php |
Public pilot profile by username: public fields only plus the pilot's groups and meets. |
Api/ActivityController.php |
The landing page activity feed: latest meet creations, meet joins, and global chat messages, merged and capped at 10. |
Api/Admin/UsersController.php |
Admin user CRUD with server-side paging, search, filtering, and sorting. Guarded by the adminapi filter plus per-action permission checks. |
-
ApiAuthFilter(aliasapiauth): rejects requests without a logged-in session with401 { "error": ... }. Applied to all mutating domain routes, chat, and the own-profile group. -
AdminApiFilter(aliasadminapi): additionally requires theadmin.accesspermission; guards everything under/api/admin/*. Each admin action then checks its concrete permission (users.view/users.create/users.edit/users.delete).
The backend check is authoritative; the frontend's RequireAuth / RequireAdmin wrappers are UX only. See Authentication and Roles.
-
OpenMeteo.php: thin wrapper around Open-Meteo's geocoding (v1/search) and forecast APIs, shared by theWeathercontroller and the meets weather endpoint. Failures returnnulland are logged, never thrown to the client as a 500. Details in Weather Integration. -
Participant.php: builds the{ id, username, name }participant shape used across meets, groups, chat, and the activity feed (name= "Vorname Nachname", falling back to the username).
-
Response contract: success is
2xxwith the documented body; validation failures are422 { errors: { field: message } }; auth errors401/403 { error }; missing resources404; conflicts (meet full, duplicate join, missing coordinates)409. -
Derived, never stored: participant counts, member counts, and meet status are computed from
meet_participants/group_membersat read time. -
CSRF is global (session mode). Mutating requests must send the
X-CSRF-TOKENheader; the SPA handles this automatically. -
Dates are
YYYY-MM-DD, timesHH:MM, timestamps ISO-8601. - Configuration that isn't committed lives in
.env(copied from theenvtemplate).
-
Meet create/edit geocoding: when a meet is created without coordinates, the backend geocodes the
spot(fallback:region) via Open-Meteo. An unresolvable spot leaves coordinatesnull, and the weather panel then shows a friendly "no forecast" note rather than an error. On edit, stored coordinates are kept when both spot and region are unchanged; otherwise re-geocoded. -
Edit rules:
maxParticipantsmay not drop below the current participant count; a past date is only rejected when the date actually changed. -
Chat channels:
messages.group_id NULL= the global "All pilots" channel; a non-nullgroup_idis that group's channel and requires membership. - Admin self-protection: an admin cannot delete, deactivate, or de-admin their own account.
FlightMeet
Code
Reference