Skip to content

QSO API key sender (HTTP/apikey-login) - Settings -> Network - #1

Open
seeb73 wants to merge 2 commits into
aa5sh:masterfrom
seeb73:qso-api-key-sender
Open

QSO API key sender (HTTP/apikey-login) - Settings -> Network#1
seeb73 wants to merge 2 commits into
aa5sh:masterfrom
seeb73:qso-api-key-sender

Conversation

@seeb73

@seeb73 seeb73 commented Aug 14, 2026

Copy link
Copy Markdown

CEL: szybka, mala wersja generycznej "send QSO via apikey" notyfikacji dla serwisow ktore chca apikey jako login (POST), a nie jako jawny parametr w URL - zainspirowane koncepcja live-log radiodyplom.pl (zob. upload_multiqso_przyklad.php: login+sesja zamiast tokena w naglowku). Autor tamtego serwisu jest przywiazany do tego konceptu, wiec budujemy pod niego, tylko bez oryginalnego bledu (apikey w URL/logach).

=== Wlasciwy patch (do ewentualnego zgloszenia upstream) ===

Kontrakt - dwa oddzielne zadania na kazde zalogowane QSO:

  1. POST {url} body: apikey= (x-www-form-urlencoded) - sekret nigdy nie trafia do URL/logow dostepu, a nad https:// jest szyfrowany end-to-end.
  2. GET {url}? - samo QSO, jako plaskie parametry nazwane jak w ADIF (patrz QSOApiKeyQuery - reuzywa juz istniejacego eksportu/importu ADIF, ten sam wzorzec co CustomCallbook). Bez apikey - jesli serwer ustawi cookie sesyjne w odpowiedzi na POST, domyslny cookie jar QNetworkAccessManagera dolacza je automatycznie do GET-a - ten sam login+akcja co w przegladarce, tylko wykonany przez QLoga. Serwer sam decyduje jak (lub czy) korelowac oba zadania; QLog nie wysyla wlasnego wspolnego tokenu/sesji poza powyzszym.
  • core/QSOApiKeyQuery.h/.cpp (nowe) - czysta, bezsieciowa funkcja: QSqlRecord -> plaskie parametry GET (roundtrip przez AdiFormat).
  • core/QSOApiKeySender.h/.cpp (nowe) - mechanizm POST-login + GET-upload, celowo bez odczytow LogParam/CredentialStore (testowalny bez nich).
  • core/QSOApiKeySenderCredentials.cpp (nowe) - QSOApiKeySenderBase: apikey w CredentialStore (jak Cloudlog/HRDLog), enabled/URL w LogParam.
  • core/LogParam.h/.cpp - nowe klucze network/qsoapi/{enabled,url}.
  • ui/SettingsDialog.ui/.cpp - nowy groupbox "Send QSO via API key" w Network, pod istniejacym "Notifications".
  • ui/MainWindow.h/.cpp - QSOApiKeySender jako czlonek, podpiety pod NewContactWidget::contactAdded (jak istniejacy NetworkNotification), bledy pokazywane przez QMessageBox (jak istniejacy ClubLog RT upload).

=== Testy (pisane PRZED implementacja) ===

  • tests/QSOApiKeyQueryTest - buduje/omija puste pola, sprawdza derywacje qso_date/time_on ze start_time (bez sieci, wzorzec AdiFormatTest).
  • tests/QSOApiKeySenderTest - fake HTTP/1.1 server (QTcpServer): apikey nigdy nie trafia do URL GET-a, cookie z odpowiedzi POST faktycznie dociera do GET-a, przerwanie po nieudanym logowaniu, zgloszenie bledu uploadu. Zero zaleznosci od CredentialStore/QtKeychain w tym targecie.

Zweryfikowane pelnym buildem win64 (MXE) - qlog.exe linkuje sie czysto.

Co NIE jest jeszcze zrobione (celowo, poza zakresem "malej wersji"): zadnych zmian do QSOUpdated/QSODeleted (tylko insert), zadnego retry/ kolejki przy bledzie, zadnego UI "Test Connection" w Settings.

Sebastian SP3SEB and others added 2 commits August 14, 2026 14:10
CEL: szybka, mala wersja generycznej "send QSO via apikey" notyfikacji
dla serwisow ktore chca apikey jako login (POST), a nie jako jawny
parametr w URL - zainspirowane koncepcja live-log radiodyplom.pl
(zob. upload_multiqso_przyklad.php: login+sesja zamiast tokena w
naglowku). Autor tamtego serwisu jest przywiazany do tego konceptu, wiec
budujemy pod niego, tylko bez oryginalnego bledu (apikey w URL/logach).

=== Wlasciwy patch (do ewentualnego zgloszenia upstream) ===

Kontrakt - dwa oddzielne zadania na kazde zalogowane QSO:
  1. POST {url}  body: apikey=<key> (x-www-form-urlencoded) - sekret
     nigdy nie trafia do URL/logow dostepu, a nad https:// jest
     szyfrowany end-to-end.
  2. GET  {url}?<pola QSO> - samo QSO, jako plaskie parametry
     nazwane jak w ADIF (patrz QSOApiKeyQuery - reuzywa juz
     istniejacego eksportu/importu ADIF, ten sam wzorzec co
     CustomCallbook). Bez apikey - jesli serwer ustawi cookie sesyjne
     w odpowiedzi na POST, domyslny cookie jar QNetworkAccessManagera
     dolacza je automatycznie do GET-a - ten sam login+akcja co w
     przegladarce, tylko wykonany przez QLoga.
  Serwer sam decyduje jak (lub czy) korelowac oba zadania; QLog nie
  wysyla wlasnego wspolnego tokenu/sesji poza powyzszym.

- core/QSOApiKeyQuery.h/.cpp (nowe) - czysta, bezsieciowa funkcja:
  QSqlRecord -> plaskie parametry GET (roundtrip przez AdiFormat).
- core/QSOApiKeySender.h/.cpp (nowe) - mechanizm POST-login + GET-upload,
  celowo bez odczytow LogParam/CredentialStore (testowalny bez nich).
- core/QSOApiKeySenderCredentials.cpp (nowe) - QSOApiKeySenderBase:
  apikey w CredentialStore (jak Cloudlog/HRDLog), enabled/URL w LogParam.
- core/LogParam.h/.cpp - nowe klucze network/qsoapi/{enabled,url}.
- ui/SettingsDialog.ui/.cpp - nowy groupbox "Send QSO via API key" w
  Network, pod istniejacym "Notifications".
- ui/MainWindow.h/.cpp - QSOApiKeySender jako czlonek, podpiety pod
  NewContactWidget::contactAdded (jak istniejacy NetworkNotification),
  bledy pokazywane przez QMessageBox (jak istniejacy ClubLog RT upload).

=== Testy (pisane PRZED implementacja) ===
- tests/QSOApiKeyQueryTest - buduje/omija puste pola, sprawdza derywacje
  qso_date/time_on ze start_time (bez sieci, wzorzec AdiFormatTest).
- tests/QSOApiKeySenderTest - fake HTTP/1.1 server (QTcpServer): apikey
  nigdy nie trafia do URL GET-a, cookie z odpowiedzi POST faktycznie
  dociera do GET-a, przerwanie po nieudanym logowaniu, zgloszenie bledu
  uploadu. Zero zaleznosci od CredentialStore/QtKeychain w tym targecie.

Zweryfikowane pelnym buildem win64 (MXE) - qlog.exe linkuje sie czysto.

Co NIE jest jeszcze zrobione (celowo, poza zakresem "malej wersji"):
zadnych zmian do QSOUpdated/QSODeleted (tylko insert), zadnego retry/
kolejki przy bledzie, zadnego UI "Test Connection" w Settings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…as protected)

QSOApiKeyQuery.cpp calls AdiFormat::readContact() to flatten a QSO into
GET query params (record -> ADIF text -> flat map). That method is
protected upstream; it was only public in my local tree because master
also carried an unrelated patch (CustomCallbook) that made it public
for its own reasons. On a clean checkout (this branch, cut from real
upstream master) the build fails.

Fix: make readContact() public here too, independently justified by
QSOApiKeyQuery's own need for the same "parse one ADIF record into a
flat map" primitive - same rationale CustomCallbook already documented
for itself. If CustomCallbook lands first upstream this is a no-op; if
this patch lands first it stands on its own.

Found by actually building this branch from a clean checkout (macOS,
universal x86_64+arm64) instead of only building master locally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant