From 1437a7de0730b8a7eed38eae36d939eb0658c6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pasternak?= Date: Thu, 14 May 2026 11:12:25 +0200 Subject: [PATCH 1/5] docs: migracja z Sphinx do MkDocs Material MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Konwersja całej dokumentacji RST na Markdown i przejście z Sphinxa na MkDocs Material. Build na Read the Docs pozostaje obsługiwany (.readthedocs.yaml przełączony na sekcję mkdocs:), nawigacja zachowana w pełni przez nav: w mkdocs.yml. - 23 plików .rst → 22 .md (pandoc 3.9 + custom post-processor dla GFM→Material admonitions i :ref:/:doc: cross-references) - usunięte: docs/conf.py, docs/Makefile, docs/make.bat - nowy: mkdocs.yml (Material theme, polish UI, autorefs, glightbox) - nowy: docs/requirements.txt (mkdocs-material >= 9.5) - docs/SECURITY.md skopiowane z root żeby SECURITY_PRACTICES.md miało target - .readthedocs.yaml: sphinx: → mkdocs: - .gitignore: docs/_build/ → site/ mkdocs build --strict zielony, 0 warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 4 +- .readthedocs.yaml | 8 +- docs/Makefile | 180 - docs/SECURITY.md | 105 + docs/SECURITY_PRACTICES.md | 4 +- docs/{advanced.rst => advanced.md} | 18 +- docs/api.md | 468 ++ docs/api.rst | 482 -- docs/authors.md | 11 + docs/authors.rst | 1 - docs/conf.py | 286 -- docs/contributing.md | 44 + docs/contributing.rst | 1 - docs/edycja_autor.md | 32 + docs/edycja_autor.rst | 33 - ...ycja_jednostka.rst => edycja_jednostka.md} | 19 +- ...edycja_uczelnia.rst => edycja_uczelnia.md} | 33 +- ..._wydawnictwo.rst => edycja_wydawnictwo.md} | 21 +- docs/history.md | 3862 +++++++++++++++++ docs/history.rst | 1 - docs/import_pracownikow.md | 86 + docs/import_pracownikow.rst | 101 - docs/importer_publikacji.md | 234 + docs/importer_publikacji.rst | 247 -- docs/index.md | 28 + docs/index.rst | 72 - docs/konfiguracja_pbn.md | 184 + docs/konfiguracja_pbn.rst | 201 - docs/make.bat | 242 -- docs/pbn.md | 83 + docs/pbn.rst | 85 - ...porty_rankingi.rst => raporty_rankingi.md} | 6 +- docs/readme.md | 10 + docs/readme.rst | 14 - docs/requirements.txt | 3 + docs/sloty.md | 295 ++ docs/sloty.rst | 330 -- docs/usage_admin.md | 397 ++ docs/usage_admin.rst | 419 -- docs/wyszukiwanie_redagowanie.md | 240 + docs/wyszukiwanie_redagowanie.rst | 286 -- ...los_publikacje.rst => zglos_publikacje.md} | 57 +- mkdocs.yml | 106 + 43 files changed, 6263 insertions(+), 3076 deletions(-) delete mode 100644 docs/Makefile create mode 100644 docs/SECURITY.md rename docs/{advanced.rst => advanced.md} (55%) create mode 100644 docs/api.md delete mode 100644 docs/api.rst create mode 100644 docs/authors.md delete mode 100644 docs/authors.rst delete mode 100755 docs/conf.py create mode 100644 docs/contributing.md delete mode 100644 docs/contributing.rst create mode 100644 docs/edycja_autor.md delete mode 100644 docs/edycja_autor.rst rename docs/{edycja_jednostka.rst => edycja_jednostka.md} (71%) rename docs/{edycja_uczelnia.rst => edycja_uczelnia.md} (71%) rename docs/{edycja_wydawnictwo.rst => edycja_wydawnictwo.md} (50%) create mode 100644 docs/history.md delete mode 100644 docs/history.rst create mode 100644 docs/import_pracownikow.md delete mode 100644 docs/import_pracownikow.rst create mode 100644 docs/importer_publikacji.md delete mode 100644 docs/importer_publikacji.rst create mode 100644 docs/index.md delete mode 100644 docs/index.rst create mode 100644 docs/konfiguracja_pbn.md delete mode 100644 docs/konfiguracja_pbn.rst delete mode 100644 docs/make.bat create mode 100644 docs/pbn.md delete mode 100644 docs/pbn.rst rename docs/{raporty_rankingi.rst => raporty_rankingi.md} (78%) create mode 100644 docs/readme.md delete mode 100644 docs/readme.rst create mode 100644 docs/requirements.txt create mode 100644 docs/sloty.md delete mode 100644 docs/sloty.rst create mode 100644 docs/usage_admin.md delete mode 100644 docs/usage_admin.rst create mode 100644 docs/wyszukiwanie_redagowanie.md delete mode 100644 docs/wyszukiwanie_redagowanie.rst rename docs/{zglos_publikacje.rst => zglos_publikacje.md} (70%) create mode 100644 mkdocs.yml diff --git a/.gitignore b/.gitignore index 81a07e3d0..075dca39d 100644 --- a/.gitignore +++ b/.gitignore @@ -53,8 +53,8 @@ coverage.xml # Django stuff: *.log -# Sphinx documentation -docs/_build/ +# MkDocs build output +site/ # PyBuilder target/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml index faed04697..74b2132d3 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,5 +5,9 @@ build: tools: python: "3.11" -sphinx: - configuration: docs/conf.py +mkdocs: + configuration: mkdocs.yml + +python: + install: + - requirements: docs/requirements.txt diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index ea0dec212..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,180 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -livehtml: - sphinx-autobuild -p 9999 -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-bpp.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-bpp.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/django-bpp" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-bpp" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 000000000..617ec144f --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,105 @@ +# Polityka bezpieczeństwa BPP + +*Security Policy — see English section below.* + +## Wspierane wersje + +Aktywnie wspierana jest najnowsza wersja z serii kalendarzowej (obecnie +`202604.x`). Łaty bezpieczeństwa wydawane są wyłącznie dla wersji aktualnie +oznaczonej jako `latest` na Docker Hub (`iplweb/bpp_appserver:latest`). + +| Wersja | Wsparcie bezpieczeństwa | +| ----------------- | ----------------------- | +| `202604.x` (latest) | Tak | +| starsze | Nie — proszę zaktualizować | + +## Zgłaszanie luk bezpieczeństwa + +**Nie otwieraj publicznego issue ani PR-a dla luk bezpieczeństwa.** Publiczne +ujawnienie przed wydaniem łaty naraża wszystkie produkcyjne instancje BPP. + +Preferowany kanał zgłoszenia (oba są prywatne): + +1. **GitHub Security Advisory** — przejdź do + [zakładki Security tego repozytorium](https://github.com/iplweb/bpp/security/advisories/new) + i wybierz „Report a vulnerability". To najszybsza ścieżka — utrzymanie + dostaje powiadomienie natychmiast. +2. **E-mail** — `security@iplweb.pl` (jeśli nie masz konta GitHub lub + wolisz e-mail). + +W zgłoszeniu opisz proszę: + +- krok-po-kroku reprodukcję, +- wpływ (co atakujący może zrobić), +- wersję BPP (`docker image inspect` lub strona `/admin/`), +- ewentualny PoC / log / screenshot. + +## SLA + +| Etap | Czas docelowy | +| --------------------- | -------------------------------- | +| Potwierdzenie odbioru | 3 dni robocze | +| Wstępna ocena (triage)| 7 dni roboczych | +| Łata: krytyczne | 14 dni od potwierdzenia | +| Łata: wysokie | 30 dni | +| Łata: średnie/niskie | następne planowane wydanie | + +Zgłaszający otrzyma podziękowanie w wpisie do `HISTORY.rst` i (na życzenie) w +opublikowanym Security Advisory, po wydaniu łaty. + +## Poza zakresem + +Następujące rzeczy **nie są** uznawane za luki bezpieczeństwa: + +- Dane testowe i fixture'y w katalogach `src/*/tests/` — to świadomie + publiczne dane. +- Aplikacja `test_bpp` — pozostawiona w produkcji wyłącznie dla starszych + referencji `ContentType` (zob. `CLAUDE.md`). +- Domyślne hasła w `docker-compose.yml` — przeznaczony tylko do dewelopmentu; + produkcyjny deployment przez `bpp-deploy` używa wstrzykniętych sekretów. +- Brak rate-limitingu na publicznych endpointach raportowych — celowo, + obciążenie reguluje warstwa nginx/cdn deploymentu. +- Self-XSS wymagający dostępu do panelu admina — Django admin zakłada + zaufaną rolę. + +## Hardening podczas korzystania + +Kilka rzeczy, których oczekujemy od deploymentu (nie są to luki BPP, ale +wpływają na bezpieczeństwo): + +- **HTTPS** wymuszone na warstwie reverse-proxy (nginx/traefik). +- **`SECRET_KEY`** unikalny per instancja, trzymany poza repozytorium. +- **Backupy bazy** szyfrowane i regularnie testowane na restore. +- **PostgreSQL/Redis** dostępne wyłącznie z sieci wewnętrznej. +- Aktualizacje obrazów Docker w cyklu zgodnym z polityką organizacji + (zob. `iplweb/bpp_appserver:latest` — Trivy gate na CRITICAL CVE). + +--- + +# Security Policy (English) + +## Supported Versions + +Only the latest calendar release (`202604.x` series, tagged `latest` on +Docker Hub as `iplweb/bpp_appserver:latest`) receives security patches. + +## Reporting a Vulnerability + +**Do not open a public issue or PR for security vulnerabilities.** Use one of +these private channels: + +1. **GitHub Security Advisory** — preferred. Go to + [Security tab](https://github.com/iplweb/bpp/security/advisories/new) → + "Report a vulnerability". +2. **Email** — `security@iplweb.pl`. + +Please include reproduction steps, impact, BPP version, and any PoC/logs. + +## SLA + +- Acknowledgement: within 3 business days. +- Triage: within 7 business days. +- Patch: critical 14d, high 30d, medium/low next scheduled release. + +Reporters are credited in `HISTORY.rst` and (on request) in the published +Security Advisory. diff --git a/docs/SECURITY_PRACTICES.md b/docs/SECURITY_PRACTICES.md index cc4c25a2a..2dec8f197 100644 --- a/docs/SECURITY_PRACTICES.md +++ b/docs/SECURITY_PRACTICES.md @@ -3,7 +3,7 @@ Dokument zbiera praktyki bezpieczeństwa stosowane w BPP, oparte na [lirantal/pypi-security-best-practices](https://github.com/lirantal/pypi-security-best-practices). -Polityka zgłaszania luk bezpieczeństwa: [SECURITY.md](../SECURITY.md). +Polityka zgłaszania luk bezpieczeństwa: [SECURITY.md](SECURITY.md). ## Spis treści @@ -125,4 +125,4 @@ cooldownem). - [pypi-security-best-practices (źródłowy doc)](https://github.com/lirantal/pypi-security-best-practices) - [uv docs — exclude-newer](https://docs.astral.sh/uv/reference/settings/#exclude-newer) - [zizmor docs](https://docs.zizmor.sh/) -- [SECURITY.md (BPP vulnerability disclosure)](../SECURITY.md) +- [SECURITY.md (BPP vulnerability disclosure)](SECURITY.md) diff --git a/docs/advanced.rst b/docs/advanced.md similarity index 55% rename from docs/advanced.rst rename to docs/advanced.md index 33a9151c3..da5d16dcb 100644 --- a/docs/advanced.rst +++ b/docs/advanced.md @@ -1,28 +1,24 @@ -Ustawienia zaawansowane ------------------------ +# Ustawienia zaawansowane W tej sekcji dokumentacji znajdują się zaawansowane ustawienia serwera. Instrukcje te przeznaczone są dla administratorów systemu operacyjnego Linux na którym działa system BPP. -Konfiguracja systemu BPP -======================== +## Konfiguracja systemu BPP Konfiguracja od wersji 202209 wzwyż powinna odbywać się przez plik `.env` umieszczony w katalogu domowym użytkownika, z którego konta uruchamiany jest serwer BPP. Zmienne konfiguracyjne będą stopniowo migrować do tego formatu. -`Przykładowy plik .env.example w repozytorium kodu na GitHub `_ +[Przykładowy plik .env.example w repozytorium kodu na GitHub](https://github.com/iplweb/bpp/blob/dev/.env.example) -`Plik django_bpp/settings/base.py repozytorium kodu na GitHub `_ +[Plik django_bpp/settings/base.py repozytorium kodu na GitHub](https://github.com/iplweb/bpp/blob/dev/src/django_bpp/settings/base.py) Zmienne można nadpisać. -Jeżeli zainstalujemy BPP korzystając z pakietu `bpp-on-ansible `_ , -to utworzy on domyślny plik ``.env``. Za zmienne odpowiada plik `config.yml `_. +Jeżeli zainstalujemy BPP korzystając z pakietu [bpp-on-ansible](https://github.com/iplweb/bpp-on-ansible) , +to utworzy on domyślny plik `.env`. Za zmienne odpowiada plik [config.yml](https://github.com/iplweb/bpp-on-ansible/blob/develop/ansible/roles/bpp-site/tasks/config.yml#L13). - -Konfiguracja LDAP (ActiveDirectory) -=================================== +## Konfiguracja LDAP (ActiveDirectory) Konfiguracja LDAP (ActiveDirectory) odbywa się za pomocą zmiennych środowiskowych lub konfiguracyjnych `AUTH_LDAP_SERVER_URI`, `AUTH_LDAP_BIND_DN`, `AUTH_LDAP_BIND_PASSWORD` oraz diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 000000000..834813d0f --- /dev/null +++ b/docs/api.md @@ -0,0 +1,468 @@ +# API systemu BPP + +System BPP oferuje API tylko-do-odczytu dla obiektów bazodanowych zawierających istotne informacje takie jak: wydawnictwa ciągłe, +wydawnictwa zwarte, patenty, autorzy, jednostki i inne. + +API dostępne jest dla użytkowników niezalogowanych. + +API dostępne jest w formie "przyjaznej developerom", to znaczy, ze po wejściu w nie możemy +korzystając ze zwykłej przeglądarki WWW zapoznać się z udostępnianymi przez API możliwościami +a następnie płynnie przełączyć się w tryb JSON, aby pobierać dane czytelne nieco mniej dla +człowieka, a bardziej dla komputera. + +![image](images/api/api_1.png) + +## API dla raportów slotu - uczelnia + +BPP umożliwia tworzenie i pobieranie raportu slotów - uczelnia za pomocą API. Taka funkcja +wymaga jednak zalogowania jako użytkownik będący członkiem grupy "generowanie raportów". + +1. Aby utworzyć raport slotów - uczelnia przez API, należy wejść w przeglądarce na stronę: + + > `/api/v1/raport_slotow_uczelnia/` + + Przeglądarka poprosi nas o zalogowanie się za pomoca loginu i hasła. Na samym dole + strony zobaczymy formularz, który umożliwia utworzenie raportu przez API: + + ![image](images/api/api_2.png) + +2. Aby utworzyć raport slotów - uczelnia przez API za pomocą polecenia `curl(1)`, + możemy w systemowej powłoce napisać: + + > ``` shell + > curl -X POST -u login:haslo https://adres.serwera/api/v1/raport_slotow_uczelnia/ + > ``` + +3. Zwrotnie otrzymamy kod JSON z danymi raportu: + + > ``` json + > { + > "id": "https://adres.serwera/api/v1/raport_slotow_uczelnia/c9d4b477-4cc5-4922-a499-fce43fd37be1/", + > "created_on": "2023-02-21T23:25:36.864007+01:00", + > "last_updated_on": "2023-02-21T23:25:36.864018+01:00", + > "started_on": null, + > "finished_on": null, + > "finished_successfully": false, + > "od_roku": 2023, + > "do_roku": 2023, + > "akcja": "slot", + > "slot": "1.0000", + > "minimalny_pk": "0.00", + > "dziel_na_jednostki_i_wydzialy": true, + > "pokazuj_zerowych": false + > } + > ``` + + W powyższym przykładzie dana nas interesująca to numer ID raportu, czyli w tym przykładzie + będzie to `c9d4b477-4cc5-4922-a499-fce43fd37be1`. + +4. Dane raportu zwracane są asynchronicznie. Oznacza to, że dopóki raport nie otrzyma wartości + w polach `finished_successfully` oraz `finished_on`, oznacza to, że nie jest jeszcze + utworzony. Należy cyklicznie odświeżać dane raportu np co 5-10 sekund, aż pojawi się + wartość w tych polach: + + `curl -u login:haslo https://adres.serwera/api/v1/raport_slotow_uczelnia/c9d4b477-4cc5-4922-a499-fce43fd37be1/` + + > > [!WARNING] + > > Utworzenie zbyt dużej ilości raportów na raz skutecznie zapcha kolejkę przetwarzania + > > asynchronicznego i utrudni kolejnym użytkownikom korzystanie z serwera. + +5. Następnie możliwe będzie pobranie pojedynczych wierszy tego raportu. Przez stronę WWW + potrzebne będzie doklikanie się do strony: + + `/api/v1/raport_slotow_uczelnia_wiersz/?parent=c9d4b477-4cc5-4922-a499-fce43fd37be1` + + Jak łatwo zauważyć, będzie tam lista wierszy raportu, zawierająca informacje o autorze, jednostce, + dyscyplinie, zebranym slocie i sumie PkD dla autora. + + ![image](images/api/api_3.png) + + Zapytanie o te wszystkie dane z pomocą polecenia `curl(1)` zwróci nam tekst w + formacie JSON: + + `curl -u login:haslo "https://adres.serwera/api/v1/raport_slotow_uczelnia_wiersz/?parent=c9d4b477-4cc5-4922-a499-fce43fd37be1" | python -m json.tool` + + **UWAGA**: tutaj na końcu nie dajemy slash. + +6. dane w formacie JSON są stronnicowane, po kilka wpisów na stronę, aby nie przeciążać serwera. Warto zwrócić + uwagę na parametry `count`, `next` i `previous`, znajdujące się w słowniku. + +## Pobieranie danych z systemu BPP przez JSON HTTP REST API + +System BPP udostępnia szereg endpoint'ów REST API dla pobierania danych o publikacjach i powiązanych obiektach. +API jest tylko-do-odczytu i nie wymaga autoryzacji dla dostępu do danych publikacji. + +Główne endpoint'y API +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +System udostępnia następujące główne endpoint'y dla pobierania danych publikacji: + +- `/api/v1/wydawnictwo_ciagle/` - wydawnictwa ciągłe (artykuły w czasopismach) +- `/api/v1/wydawnictwo_zwarte/` - wydawnictwa zwarte (książki, rozdziały) +- `/api/v1/patent/` - patenty +- `/api/v1/praca_doktorska/` - prace doktorskie +- `/api/v1/praca_habilitacyjna/` - prace habilitacyjne + +Dane pomocnicze dostępne są przez następujące endpoint'y: + +- `/api/v1/autor/` - autorzy +- `/api/v1/jednostka/` - jednostki organizacyjne +- `/api/v1/uczelnia/` - uczelnie +- `/api/v1/wydawca/` - wydawcy +- `/api/v1/zrodlo/` - źródła publikacji +- `/api/v1/charakter_formalny/` - charaktery formalne + +Przykłady użycia CURL +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +1. **Pobranie listy wydawnictw ciągłych:** + + ``` shell + curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/" | python -m json.tool + ``` + + To polecenie zwróci listę wydawnictw ciągłych w formacie JSON z paginacją. + +2. **Pobranie konkretnego wydawnictwa ciągłego:** + + ``` shell + curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/123/" | python -m json.tool + ``` + + Gdzie `123` to ID konkretnego wydawnictwa. + +3. **Filtrowanie wydawnictw po roku:** + + ``` shell + curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/?rok__gte=2020&rok__lte=2023" | python -m json.tool + ``` + + To polecenie zwróci wydawnictwa z lat 2020-2023. + +4. **Pobranie wydawnictw zmienionych w określonym okresie:** + + ``` shell + curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/?ostatnio_zmieniony__gte=2023-01-01T00:00:00Z" | python -m json.tool + ``` + + To polecenie zwróci wydawnictwa zmienione od 1 stycznia 2023 roku. + +5. **Pobranie listy autorów:** + + ``` shell + curl "https://adres.serwera/api/v1/autor/" | python -m json.tool + ``` + +6. **Pobranie konkretnego autora:** + + ``` shell + curl "https://adres.serwera/api/v1/autor/456/" | python -m json.tool + ``` + + Gdzie `456` to ID konkretnego autora. + +Przykłady użycia w Postman +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +!!! note + + Postman to darmowe narzędzie do testowania API. Można je pobrać ze strony + + +1. **Konfiguracja podstawowa:** + - Method: GET + - URL: `https://adres.serwera/api/v1/wydawnictwo_ciagle/` + - Headers: `Accept: application/json` +2. **Pobieranie z filtrowaniem po roku:** + - Method: GET + - URL: `https://adres.serwera/api/v1/wydawnictwo_ciagle/` + - Params: + - `rok__gte`: `2020` + - `rok__lte`: `2023` +3. **Pobieranie z paginacją:** + - Method: GET + - URL: `https://adres.serwera/api/v1/wydawnictwo_ciagle/` + - Params: + - `page`: `2` + - `page_size`: `50` +4. **Pobieranie konkretnego rekordu:** + - Method: GET + - URL: `https://adres.serwera/api/v1/wydawnictwo_ciagle/123/` + +Format odpowiedzi +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +API zwraca dane w formacie JSON. Przykład odpowiedzi dla listy wydawnictw: + +``` json +{ + "count": 1500, + "next": "https://adres.serwera/api/v1/wydawnictwo_ciagle/?page=2", + "previous": null, + "results": [ + { + "id": 123, + "tytul": "Przykładowy tytuł artykułu", + "rok": 2023, + "charakter_formalny": { + "nazwa": "Artykuł w czasopiśmie" + }, + "autorzy_set": [ + { + "autor": { + "imiona": "Jan", + "nazwisko": "Kowalski" + } + } + ], + "ostatnio_zmieniony": "2023-12-01T10:30:00Z" + } + ] +} +``` + +Parametry filtrowania +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +Większość endpoint'ów obsługuje następujące parametry filtrowania: + +- `rok` - filtrowanie po roku publikacji +- `rok__gte` - publikacje od podanego roku (włącznie) +- `rok__lte` - publikacje do podanego roku (włącznie) +- `ostatnio_zmieniony` - filtrowanie po dacie ostatniej modyfikacji +- `ostatnio_zmieniony__gte` - rekordy zmienione od podanej daty +- `charakter_formalny` - filtrowanie po charakterze formalnym publikacji + +Paginacja +\~\~\~\~\~\~\~~ + +Wszystkie listy są paginowane. Odpowiedzi zawierają: + +- `count` - łączna liczba rekordów +- `next` - URL do następnej strony (jeśli istnieje) +- `previous` - URL do poprzedniej strony (jeśli istnieje) +- `results` - aktualne wyniki + +Domyślnie zwracane jest 20 rekordów na stronę. Można to zmienić parametrem `page_size`. + +## API dla ostatnich publikacji autora + +System BPP udostępnia specjalny endpoint umożliwiający pobranie listy ostatnich publikacji konkretnego autora. +Jest to przydatne dla autorów, którzy chcą wyświetlić swoją listę prac na własnej stronie internetowej. + +### Endpoint + +Aby pobrać ostatnie publikacje autora, należy użyć następującego endpoint'u: + +`/api/v1/recent_author_publications/{id}/` + +Gdzie `{id}` to identyfikator autora w systemie BPP. + +Funkcjonalność +\~\~\~\~\~\~\~\~\~\~\~\~~ + +- Zwraca 25 ostatnich publikacji autora +- Publikacje są sortowane według daty ostatniej modyfikacji (od najnowszej) +- Dla każdej publikacji zwracany jest: + - Identyfikator publikacji + - Pełny opis bibliograficzny + - Data ostatniej modyfikacji + - URL do szczegółowej strony publikacji w systemie BPP + +Format odpowiedzi +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +``` json +{ + "autor_id": 123, + "autor_nazwa": "prof. dr hab. Jan Kowalski", + "count": 25, + "publications": [ + { + "id": "[1, 456]", + "opis_bibliograficzny": "Kowalski J., Nowak A.: Przykładowy tytuł artykułu. Czasopismo Naukowe 2023, vol. 15, s. 123-145.", + "ostatnio_zmieniony": "2023-12-15T14:30:00+01:00", + "url": "https://bpp.uczelnia.pl/bpp/browse/praca/przykładowy-tytuł-artykułu-kowalski-j-nowak-a-2023" + }, + { + "id": "[1, 457]", + "opis_bibliograficzny": "Kowalski J.: Monografia naukowa. Wydawnictwo Uczelniane, Warszawa 2023, ISBN 978-83-1234-567-8.", + "ostatnio_zmieniony": "2023-11-20T10:15:00+01:00", + "url": "https://bpp.uczelnia.pl/bpp/browse/praca/monografia-naukowa-kowalski-j-2023" + } + ] +} +``` + +Przykład użycia CURL +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +``` shell +curl "https://bpp.uczelnia.pl/api/v1/recent_author_publications/123/" | python -m json.tool +``` + +### Przykład integracji na stronie WWW autora + +Poniżej znajduje się przykładowy kod JavaScript, który może być użyty na stronie internetowej autora +do automatycznego pobierania i wyświetlania listy jego publikacji: + +``` html + + + + + Moje publikacje + + + +
+

Moje ostatnie publikacje

+
+ Ładowanie publikacji... +
+
+ + + + +``` + +Uwagi dotyczące CORS +\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~~ + +CORS (Cross-Origin Resource Sharing) to mechanizm bezpieczeństwa przeglądarek internetowych, który kontroluje +dostęp do zasobów między różnymi domenami. Gdy strona internetowa próbuje pobrać dane z innej domeny +(np. strona autora z domeny `autor.pl` próbuje pobrać dane z `bpp.uczelnia.pl`), przeglądarka +sprawdza, czy serwer docelowy zezwala na takie połączenie. + +System BPP domyślnie konfiguruje nagłówki CORS tak, aby umożliwić pobieranie danych API przez przeglądarki +internetowe z różnych lokalizacji. Oznacza to, że endpoint `/api/v1/recent_author_publications/` jest +standardowo dostępny dla zewnętrznych stron WWW. + +Jednak ze względu na różne uwarunkowania konfiguracyjne (np. dodatkowe proxy, loadbalancery, specyficzne +ustawienia serwera WWW lub wymagania bezpieczeństwa instytucji), domyślna konfiguracja CORS może okazać się +niewystarczająca. + +W przypadku wystąpienia błędów CORS (widocznych w konsoli przeglądarki jako błędy typu "CORS policy blocked"), +należy skontaktować się z administratorem systemu BPP w celu dostosowania konfiguracji do konkretnych potrzeb. diff --git a/docs/api.rst b/docs/api.rst deleted file mode 100644 index c7ab1ab43..000000000 --- a/docs/api.rst +++ /dev/null @@ -1,482 +0,0 @@ -API systemu BPP -=============== - -System BPP oferuje API tylko-do-odczytu dla obiektów bazodanowych zawierających istotne informacje takie jak: wydawnictwa ciągłe, -wydawnictwa zwarte, patenty, autorzy, jednostki i inne. - -API dostępne jest dla użytkowników niezalogowanych. - -API dostępne jest w formie "przyjaznej developerom", to znaczy, ze po wejściu w nie możemy -korzystając ze zwykłej przeglądarki WWW zapoznać się z udostępnianymi przez API możliwościami -a następnie płynnie przełączyć się w tryb JSON, aby pobierać dane czytelne nieco mniej dla -człowieka, a bardziej dla komputera. - -.. image:: images/api/api_1.png - -API dla raportów slotu - uczelnia ---------------------------------- - -BPP umożliwia tworzenie i pobieranie raportu slotów - uczelnia za pomocą API. Taka funkcja -wymaga jednak zalogowania jako użytkownik będący członkiem grupy "generowanie raportów". - -#. Aby utworzyć raport slotów - uczelnia przez API, należy wejść w przeglądarce na stronę: - - ``/api/v1/raport_slotow_uczelnia/`` - - Przeglądarka poprosi nas o zalogowanie się za pomoca loginu i hasła. Na samym dole - strony zobaczymy formularz, który umożliwia utworzenie raportu przez API: - - .. image:: images/api/api_2.png - -#. Aby utworzyć raport slotów - uczelnia przez API za pomocą polecenia ``curl(1)``, - możemy w systemowej powłoce napisać: - - .. code-block:: shell - - curl -X POST -u login:haslo https://adres.serwera/api/v1/raport_slotow_uczelnia/ - -#. Zwrotnie otrzymamy kod JSON z danymi raportu: - - .. code-block:: json - - { - "id": "https://adres.serwera/api/v1/raport_slotow_uczelnia/c9d4b477-4cc5-4922-a499-fce43fd37be1/", - "created_on": "2023-02-21T23:25:36.864007+01:00", - "last_updated_on": "2023-02-21T23:25:36.864018+01:00", - "started_on": null, - "finished_on": null, - "finished_successfully": false, - "od_roku": 2023, - "do_roku": 2023, - "akcja": "slot", - "slot": "1.0000", - "minimalny_pk": "0.00", - "dziel_na_jednostki_i_wydzialy": true, - "pokazuj_zerowych": false - } - - W powyższym przykładzie dana nas interesująca to numer ID raportu, czyli w tym przykładzie - będzie to ``c9d4b477-4cc5-4922-a499-fce43fd37be1``. - -#. Dane raportu zwracane są asynchronicznie. Oznacza to, że dopóki raport nie otrzyma wartości - w polach ``finished_successfully`` oraz ``finished_on``, oznacza to, że nie jest jeszcze - utworzony. Należy cyklicznie odświeżać dane raportu np co 5-10 sekund, aż pojawi się - wartość w tych polach: - - ``curl -u login:haslo https://adres.serwera/api/v1/raport_slotow_uczelnia/c9d4b477-4cc5-4922-a499-fce43fd37be1/`` - - .. warning:: - - Utworzenie zbyt dużej ilości raportów na raz skutecznie zapcha kolejkę przetwarzania - asynchronicznego i utrudni kolejnym użytkownikom korzystanie z serwera. - - -#. Następnie możliwe będzie pobranie pojedynczych wierszy tego raportu. Przez stronę WWW - potrzebne będzie doklikanie się do strony: - - ``/api/v1/raport_slotow_uczelnia_wiersz/?parent=c9d4b477-4cc5-4922-a499-fce43fd37be1`` - - Jak łatwo zauważyć, będzie tam lista wierszy raportu, zawierająca informacje o autorze, jednostce, - dyscyplinie, zebranym slocie i sumie PkD dla autora. - - .. image:: images/api/api_3.png - - Zapytanie o te wszystkie dane z pomocą polecenia ``curl(1)`` zwróci nam tekst w - formacie JSON: - - ``curl -u login:haslo "https://adres.serwera/api/v1/raport_slotow_uczelnia_wiersz/?parent=c9d4b477-4cc5-4922-a499-fce43fd37be1" | python -m json.tool`` - - **UWAGA**: tutaj na końcu nie dajemy slash. - -#. dane w formacie JSON są stronnicowane, po kilka wpisów na stronę, aby nie przeciążać serwera. Warto zwrócić - uwagę na parametry ``count``, ``next`` i ``previous``, znajdujące się w słowniku. - -Pobieranie danych z systemu BPP przez JSON HTTP REST API --------------------------------------------------------- - -System BPP udostępnia szereg endpoint'ów REST API dla pobierania danych o publikacjach i powiązanych obiektach. -API jest tylko-do-odczytu i nie wymaga autoryzacji dla dostępu do danych publikacji. - -Główne endpoint'y API -~~~~~~~~~~~~~~~~~~~~ - -System udostępnia następujące główne endpoint'y dla pobierania danych publikacji: - -* ``/api/v1/wydawnictwo_ciagle/`` - wydawnictwa ciągłe (artykuły w czasopismach) -* ``/api/v1/wydawnictwo_zwarte/`` - wydawnictwa zwarte (książki, rozdziały) -* ``/api/v1/patent/`` - patenty -* ``/api/v1/praca_doktorska/`` - prace doktorskie -* ``/api/v1/praca_habilitacyjna/`` - prace habilitacyjne - -Dane pomocnicze dostępne są przez następujące endpoint'y: - -* ``/api/v1/autor/`` - autorzy -* ``/api/v1/jednostka/`` - jednostki organizacyjne -* ``/api/v1/uczelnia/`` - uczelnie -* ``/api/v1/wydawca/`` - wydawcy -* ``/api/v1/zrodlo/`` - źródła publikacji -* ``/api/v1/charakter_formalny/`` - charaktery formalne - -Przykłady użycia CURL -~~~~~~~~~~~~~~~~~~~~ - -#. **Pobranie listy wydawnictw ciągłych:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/" | python -m json.tool - - To polecenie zwróci listę wydawnictw ciągłych w formacie JSON z paginacją. - -#. **Pobranie konkretnego wydawnictwa ciągłego:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/123/" | python -m json.tool - - Gdzie ``123`` to ID konkretnego wydawnictwa. - -#. **Filtrowanie wydawnictw po roku:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/?rok__gte=2020&rok__lte=2023" | python -m json.tool - - To polecenie zwróci wydawnictwa z lat 2020-2023. - -#. **Pobranie wydawnictw zmienionych w określonym okresie:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/wydawnictwo_ciagle/?ostatnio_zmieniony__gte=2023-01-01T00:00:00Z" | python -m json.tool - - To polecenie zwróci wydawnictwa zmienione od 1 stycznia 2023 roku. - -#. **Pobranie listy autorów:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/autor/" | python -m json.tool - -#. **Pobranie konkretnego autora:** - - .. code-block:: shell - - curl "https://adres.serwera/api/v1/autor/456/" | python -m json.tool - - Gdzie ``456`` to ID konkretnego autora. - -Przykłady użycia w Postman -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. note:: - Postman to darmowe narzędzie do testowania API. Można je pobrać ze strony https://www.postman.com/downloads/ - -#. **Konfiguracja podstawowa:** - - * Method: GET - * URL: ``https://adres.serwera/api/v1/wydawnictwo_ciagle/`` - * Headers: ``Accept: application/json`` - -#. **Pobieranie z filtrowaniem po roku:** - - * Method: GET - * URL: ``https://adres.serwera/api/v1/wydawnictwo_ciagle/`` - * Params: - * ``rok__gte``: ``2020`` - * ``rok__lte``: ``2023`` - -#. **Pobieranie z paginacją:** - - * Method: GET - * URL: ``https://adres.serwera/api/v1/wydawnictwo_ciagle/`` - * Params: - * ``page``: ``2`` - * ``page_size``: ``50`` - -#. **Pobieranie konkretnego rekordu:** - - * Method: GET - * URL: ``https://adres.serwera/api/v1/wydawnictwo_ciagle/123/`` - -Format odpowiedzi -~~~~~~~~~~~~~~~~ - -API zwraca dane w formacie JSON. Przykład odpowiedzi dla listy wydawnictw: - -.. code-block:: json - - { - "count": 1500, - "next": "https://adres.serwera/api/v1/wydawnictwo_ciagle/?page=2", - "previous": null, - "results": [ - { - "id": 123, - "tytul": "Przykładowy tytuł artykułu", - "rok": 2023, - "charakter_formalny": { - "nazwa": "Artykuł w czasopiśmie" - }, - "autorzy_set": [ - { - "autor": { - "imiona": "Jan", - "nazwisko": "Kowalski" - } - } - ], - "ostatnio_zmieniony": "2023-12-01T10:30:00Z" - } - ] - } - -Parametry filtrowania -~~~~~~~~~~~~~~~~~~~ - -Większość endpoint'ów obsługuje następujące parametry filtrowania: - -* ``rok`` - filtrowanie po roku publikacji -* ``rok__gte`` - publikacje od podanego roku (włącznie) -* ``rok__lte`` - publikacje do podanego roku (włącznie) -* ``ostatnio_zmieniony`` - filtrowanie po dacie ostatniej modyfikacji -* ``ostatnio_zmieniony__gte`` - rekordy zmienione od podanej daty -* ``charakter_formalny`` - filtrowanie po charakterze formalnym publikacji - -Paginacja -~~~~~~~~ - -Wszystkie listy są paginowane. Odpowiedzi zawierają: - -* ``count`` - łączna liczba rekordów -* ``next`` - URL do następnej strony (jeśli istnieje) -* ``previous`` - URL do poprzedniej strony (jeśli istnieje) -* ``results`` - aktualne wyniki - -Domyślnie zwracane jest 20 rekordów na stronę. Można to zmienić parametrem ``page_size``. - -API dla ostatnich publikacji autora ------------------------------------ - -System BPP udostępnia specjalny endpoint umożliwiający pobranie listy ostatnich publikacji konkretnego autora. -Jest to przydatne dla autorów, którzy chcą wyświetlić swoją listę prac na własnej stronie internetowej. - -Endpoint -~~~~~~~~ - -Aby pobrać ostatnie publikacje autora, należy użyć następującego endpoint'u: - -``/api/v1/recent_author_publications/{id}/`` - -Gdzie ``{id}`` to identyfikator autora w systemie BPP. - -Funkcjonalność -~~~~~~~~~~~~~ - -* Zwraca 25 ostatnich publikacji autora -* Publikacje są sortowane według daty ostatniej modyfikacji (od najnowszej) -* Dla każdej publikacji zwracany jest: - - * Identyfikator publikacji - * Pełny opis bibliograficzny - * Data ostatniej modyfikacji - * URL do szczegółowej strony publikacji w systemie BPP - -Format odpowiedzi -~~~~~~~~~~~~~~~~ - -.. code-block:: json - - { - "autor_id": 123, - "autor_nazwa": "prof. dr hab. Jan Kowalski", - "count": 25, - "publications": [ - { - "id": "[1, 456]", - "opis_bibliograficzny": "Kowalski J., Nowak A.: Przykładowy tytuł artykułu. Czasopismo Naukowe 2023, vol. 15, s. 123-145.", - "ostatnio_zmieniony": "2023-12-15T14:30:00+01:00", - "url": "https://bpp.uczelnia.pl/bpp/browse/praca/przykładowy-tytuł-artykułu-kowalski-j-nowak-a-2023" - }, - { - "id": "[1, 457]", - "opis_bibliograficzny": "Kowalski J.: Monografia naukowa. Wydawnictwo Uczelniane, Warszawa 2023, ISBN 978-83-1234-567-8.", - "ostatnio_zmieniony": "2023-11-20T10:15:00+01:00", - "url": "https://bpp.uczelnia.pl/bpp/browse/praca/monografia-naukowa-kowalski-j-2023" - } - ] - } - -Przykład użycia CURL -~~~~~~~~~~~~~~~~~~ - -.. code-block:: shell - - curl "https://bpp.uczelnia.pl/api/v1/recent_author_publications/123/" | python -m json.tool - -Przykład integracji na stronie WWW autora -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Poniżej znajduje się przykładowy kod JavaScript, który może być użyty na stronie internetowej autora -do automatycznego pobierania i wyświetlania listy jego publikacji: - -.. code-block:: html - - - - - - Moje publikacje - - - -
-

Moje ostatnie publikacje

-
- Ładowanie publikacji... -
-
- - - - - -Uwagi dotyczące CORS -~~~~~~~~~~~~~~~~~~~ - -CORS (Cross-Origin Resource Sharing) to mechanizm bezpieczeństwa przeglądarek internetowych, który kontroluje -dostęp do zasobów między różnymi domenami. Gdy strona internetowa próbuje pobrać dane z innej domeny -(np. strona autora z domeny ``autor.pl`` próbuje pobrać dane z ``bpp.uczelnia.pl``), przeglądarka -sprawdza, czy serwer docelowy zezwala na takie połączenie. - -System BPP domyślnie konfiguruje nagłówki CORS tak, aby umożliwić pobieranie danych API przez przeglądarki -internetowe z różnych lokalizacji. Oznacza to, że endpoint ``/api/v1/recent_author_publications/`` jest -standardowo dostępny dla zewnętrznych stron WWW. - -Jednak ze względu na różne uwarunkowania konfiguracyjne (np. dodatkowe proxy, loadbalancery, specyficzne -ustawienia serwera WWW lub wymagania bezpieczeństwa instytucji), domyślna konfiguracja CORS może okazać się -niewystarczająca. - -W przypadku wystąpienia błędów CORS (widocznych w konsoli przeglądarki jako błędy typu "CORS policy blocked"), -należy skontaktować się z administratorem systemu BPP w celu dostosowania konfiguracji do konkretnych potrzeb. diff --git a/docs/authors.md b/docs/authors.md new file mode 100644 index 000000000..a09344f29 --- /dev/null +++ b/docs/authors.md @@ -0,0 +1,11 @@ +# Autorzy + +## Programiści + +- Michał Pasternak \ + +## Bibliotekarze + +- Elżbieta Drożdż \ +- Renata Birska \ +- Małgorzata Zając \ diff --git a/docs/authors.rst b/docs/authors.rst deleted file mode 100644 index e122f914a..000000000 --- a/docs/authors.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../AUTHORS.rst diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100755 index fdf331003..000000000 --- a/docs/conf.py +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/env python -# -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another -# directory, add these directories to sys.path here. If the directory is -# relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -# Get the project root dir, which is the parent dir of this -cwd = os.getcwd() -project_root = os.path.dirname(cwd) - -# Insert the project root dir as the first element in the PYTHONPATH. -# This lets us ensure that the source package is imported, and that its -# version is used. -sys.path.insert(0, os.path.join(project_root, "src")) - -from django_bpp.version import VERSION - -# -- General configuration --------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.viewcode", - "sphinx.ext.imgmath", - "sphinx.ext.autosectionlabel", -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix of source filenames. -source_suffix = ".rst" - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = "Bibliografia Publikacji Pracowników" -copyright = "2005-2025, iplweb.pl Michał Pasternak" - -# The version info for the project you're documenting, acts as replacement -# for |version| and |release|, also used in various other places throughout -# the built documents. -# -# The short X.Y version. -version = VERSION -# The full version, including alpha/beta/rc tags. -version = VERSION - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to -# some non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built -# documents. -# keep_warnings = False - - -# -- Options for HTML output ------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "default" - -# Theme options are theme-specific and customize the look and feel of a -# theme further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as -# html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the -# top of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon -# of the docs. This file should be a Windows icon file (.ico) being -# 16x16 or 32x32 pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) -# here, relative to this directory. They are copied after the builtin -# static files, so a file named "default.css" will overwrite the builtin -# "default.css". -html_static_path = ["_static"] - -# If not '', a 'Last updated on:' timestamp is inserted at every page -# bottom, using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names -# to template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. -# Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. -# Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages -# will contain a tag referring to it. The value of this option -# must be the base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = "django_bppdoc" - - -# -- Options for LaTeX output ------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ( - "index", - "django-bpp.tex", - "Bibliografia Publikacji Pracowników", - "Michał Pasternak", - "manual", - ), -] - -# The name of an image file (relative to this directory) to place at -# the top of the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings -# are parts, not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output ------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - "index", - "django-bpp", - "Bibliografia Publikacji Pracowników", - ["Michał Pasternak"], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ---------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - "index", - "amms_planop2xls", - "Bibliografia Publikacji Pracowników", - "Michał Pasternak", - "django_bpp", - "One line description of project.", - "Miscellaneous", - ), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 000000000..4592c438a --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,44 @@ +# Rozwijanie oprogramowania + +Cenimy sobie wszystkie uwagi, nawet te krytyczne. Każda z nich może pomóc, podobnie +każdy z nas może zostać współautorem niniejszego oprogramowania. + +Możesz dołożyć się do tego projektu na różne sposoby: + +## Zgłaszanie błędów + +Zgłaszaj błędy w oprogramowaniu pod adresem +[github.com/iplweb/bpp/issues](https://github.com/iplweb/bpp/issues). + +Jeżeli zgłaszasz błąd, prosimy, opisz: + +- Twój system operacyjny i wersję przeglądarki WWW, +- szczegóły dotyczące konfiguracji Twojego komputera, które mogą pomóc + w powieleniu a następnie usunięciu błędu, +- szczegółową instrukcję krok-po-kroku jak spowodować wystąpienie błędu + +## Naprawianie błędów + +Przejrzyj zgłoszenia na GitHub w poszukiwaniu błędów, które możesz naprawić. + +## Zaimplementuj nowe funkcje + +Przejrzyj zgłoszenia na GitHub w poszukiwaniu zgłoszeń zawierających +zapotrzebowanie na nowe funkcje. Wszystko, co oznaczone "enhancement" +lub "help wanted" czeka na osobę, która się tym zajmie. + +## Napisz dokumentację + +BPP zawsze może skorzystać z nowej dokumentacji, bądź to w formie instrukcji, +docstrings lub artykułów na sieci, prezentacji itp. + +## Zgłoś uwagi + +Najlepszy sposób na zgłoszenie swoich uwag to wypełnienie formularza pod adresem +[github.com/iplweb/bpp/issues](https://github.com/iplweb/bpp/issues). + +Jeżeli proponujesz nową funkcję: + +- Wyjaśnij, w jaki sposób ma działać +- Pamiętaj, że ten projekt rozwijany jest na zasadach opensource i Twój wkład + jest mile widziany diff --git a/docs/contributing.rst b/docs/contributing.rst deleted file mode 100644 index e582053ea..000000000 --- a/docs/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CONTRIBUTING.rst diff --git a/docs/edycja_autor.md b/docs/edycja_autor.md new file mode 100644 index 000000000..4a9b48aa6 --- /dev/null +++ b/docs/edycja_autor.md @@ -0,0 +1,32 @@ +# Edycja danych autorów + +## Pole *Aktualne miejsce pracy* dla autora + +Wartość pola *Aktualne miejsce pracy* która widnieje w module redagowania +dla Autora jest wartością tylko-do-odczytu a jej wartość obliczana jest na podstawie +wpisów powiązań autora z jednostką: + +![Zrzut ekranu przedstawiający kilka powiązań autora z jednostkami.](images/admin/autor_jednostka/autor_jednostka.png) + +!!! note + + Pole *Aktualne miejsce pracy* używane jest w raportach oraz do + podpowiadania jednostki przy dopisywaniu autora do rekordu publikacji. + + +Algorytm ustalania aktualnego miejsca pracy działa w sposób następujący: + +1. jeżeli któreś z miejsc pracy ma atrybut *Podstawowe miejce pracy* ustawiony na "TAK" i data + zakończenia pracy jest pusta lub większa od obecnej, to takie miejsce będzie wybrane jako aktualne +2. jeżeli autor nie ma żadnego miejsca pracy ustawionego jako podstawowe, to system jako aktualne + miejsce pracy wybierze to, w którym autor nie zakończył pracy (data zakończenia pracy jest pusta + lub większa od obecnej) i gdzie autor rozpoczął pracę najpóźniej (data rozpoczęcia pracy jest + najwyższa) +3. jeżeli autor ma kilka miejsc pracy i w żadnym nie ma ustawionego atrybutu *Podstawowe miejsce pracy* + oraz daty rozpoczęcia i zakończenia pracy są puste, system jako *Aktualne miejsce pracy* wybierze + to powiązanie, które do systemu BPP zostało dopisane najpóźniej (jego numer ID jest największy) + +!!! warning + + dany autor może mieć tylko jedno powiązanie oznaczone jako *Podstawowe miejsce pracy*. + diff --git a/docs/edycja_autor.rst b/docs/edycja_autor.rst deleted file mode 100644 index 9292fd758..000000000 --- a/docs/edycja_autor.rst +++ /dev/null @@ -1,33 +0,0 @@ -Edycja danych autorów -===================== - -Pole *Aktualne miejsce pracy* dla autora ----------------------------------------- - -Wartość pola *Aktualne miejsce pracy* która widnieje w module redagowania -dla Autora jest wartością tylko-do-odczytu a jej wartość obliczana jest na podstawie -wpisów powiązań autora z jednostką: - -.. image:: images/admin/autor_jednostka/autor_jednostka.png - :alt: Zrzut ekranu przedstawiający kilka powiązań autora z jednostkami. - -.. note:: Pole *Aktualne miejsce pracy* używane jest w raportach oraz do - podpowiadania jednostki przy dopisywaniu autora do rekordu publikacji. - -Algorytm ustalania aktualnego miejsca pracy działa w sposób następujący: - -#. jeżeli któreś z miejsc pracy ma atrybut *Podstawowe miejce pracy* ustawiony na "TAK" i data - zakończenia pracy jest pusta lub większa od obecnej, to takie miejsce będzie wybrane jako aktualne - -#. jeżeli autor nie ma żadnego miejsca pracy ustawionego jako podstawowe, to system jako aktualne - miejsce pracy wybierze to, w którym autor nie zakończył pracy (data zakończenia pracy jest pusta - lub większa od obecnej) i gdzie autor rozpoczął pracę najpóźniej (data rozpoczęcia pracy jest - najwyższa) - -#. jeżeli autor ma kilka miejsc pracy i w żadnym nie ma ustawionego atrybutu *Podstawowe miejsce pracy* - oraz daty rozpoczęcia i zakończenia pracy są puste, system jako *Aktualne miejsce pracy* wybierze - to powiązanie, które do systemu BPP zostało dopisane najpóźniej (jego numer ID jest największy) - - - -.. warning:: dany autor może mieć tylko jedno powiązanie oznaczone jako *Podstawowe miejsce pracy*. diff --git a/docs/edycja_jednostka.rst b/docs/edycja_jednostka.md similarity index 71% rename from docs/edycja_jednostka.rst rename to docs/edycja_jednostka.md index 4778c7fb3..0b1a16dbd 100644 --- a/docs/edycja_jednostka.rst +++ b/docs/edycja_jednostka.md @@ -1,23 +1,19 @@ -Edycja danych jednostek -======================= +# Edycja danych jednostek -Pole *Aktualny wydział* ------------------------ +## Pole *Aktualny wydział* Pole *Aktualny wydział* jest polem tylko-do-odczytu, zaś jego wartość obliczana jest na podstawie powiązań jednostki z wydziałem. Rozwiązane jest to w ten sposób, ponieważ jednostki mogą w niektórych przypadkach zmieniać wydział. W takiej sytuacji można wpisać datę takiej zmiany. -Pole *Skupia pracowników* -------------------------- +## Pole *Skupia pracowników* Pole używane w raportach. Określa, czy jednostka skupia obecnych, aktualnych, żyjących pracowników uczelni. W przypadku jednostek "wirtualnych" (jednostek, które faktycznie nie istnieją, a dodane do BPP zostały celem usprawnienia zarządzania danymi) wskazane jest odznaczenie tego pola. -Pole *Zarządzaj automatycznie* ------------------------------- +## Pole *Zarządzaj automatycznie* Pole to określa, czy dana jednostka będzie zarządzana przez system automatycznie przy imporcie danych z zewnętrznych źródeł. @@ -27,5 +23,8 @@ Przykładowo, jeżeli utworzymy jednostkę "wirtualną" to przy synchronizacji d ulegałaby skasowaniu bądź zaznaczeniu, że nie jest jednostką aktualną. Zatem, dla takich jednostek, należy odznaczyć to pole. -.. note:: W obecnym kształcie systemu BPP, pole to używane jest przy :ref:`imporcie pracowników ` - przez procedurę :ref:`odpinania nieaktualnych miejsc pracy `. +!!! note + + W obecnym kształcie systemu BPP, pole to używane jest przy [imporcie pracowników](import_pracownikow.md) + przez procedurę [odpinania nieaktualnych miejsc pracy](import_pracownikow.md#odpinanie-nieaktualnych-miejsc-pracy). + diff --git a/docs/edycja_uczelnia.rst b/docs/edycja_uczelnia.md similarity index 71% rename from docs/edycja_uczelnia.rst rename to docs/edycja_uczelnia.md index 76811bea8..8d1a133ba 100644 --- a/docs/edycja_uczelnia.rst +++ b/docs/edycja_uczelnia.md @@ -1,49 +1,43 @@ -Edycja danych uczelni -===================== +# Edycja danych uczelni -Wejście do ustawień Uczelni ---------------------------- +## Wejście do ustawień Uczelni Aby wejść do ustawień Uczelni, musimy najpierw się zalogować do systemu. W tym celu na pierwszym ekranie na górnej belce nawigacji klikamy w "zaloguj" -.. image:: images/admin/edycja_uczelnia/edycja_uczelnia_0.png +![image](images/admin/edycja_uczelnia/edycja_uczelnia_0.png) Po zalogowaniu się, na górnej belce nawigacji pojawi się opcja "redagowanie": -.. image:: images/admin/edycja_uczelnia/edycja_uczelnia_1.png +![image](images/admin/edycja_uczelnia/edycja_uczelnia_1.png) Po wejściu w redagowanie, z górnej belki nawigacji wybieramy "Struktura" a następnie "Uczelnia": -.. image:: images/admin/edycja_uczelnia/edycja_uczelnia_2.png +![image](images/admin/edycja_uczelnia/edycja_uczelnia_2.png) W systemie powinien być jeden rekord określający dane uczelni. Aby wejśc dalej, klikamy w nazwę Uczelni: -.. image:: images/admin/edycja_uczelnia/edycja_uczelnia_3.png +![image](images/admin/edycja_uczelnia/edycja_uczelnia_3.png) Następnie otworzy nam się puszka Pandory tzn. formularz ustawień uczelni. W chwili tworzenia niniejszej dokumentacji zajmuje on około 5 ekranów. Użytkownicy końcowi a nawet administratorzy nie będą tu zaglądać zbyt często, ale mimo to doradzamy rozwagę w edycji ustawień obiektu uczelnia. -Integracja z Web Of Science ---------------------------- +## Integracja z Web Of Science Po rozwinięciu zakładki "Clarivate Analytics API" możemy uzupełnić nazwę użytkownika i hasło do Clarivate Analytics API. W ten sposób będziemy mogli zaciągać liczbę cytowań dla rekordów i autorów. -Integracja z PBN ----------------- +## Integracja z PBN Jeżeli w PBN uzyskaliśmy rolę "Menedżer aplikacji", możemy utworzyc token aplikacji i wpisać te dane do BPP. Umożliwi -to autoryzowanie użytkownika loginem w PBN (na głównej stronie, menu operacje -> autoryzuj w PBN) a następnie +to autoryzowanie użytkownika loginem w PBN (na głównej stronie, menu operacje -\> autoryzuj w PBN) a następnie możliwe będzie wysyłanie prac do PBN przy ich zapisywaniu. W ten sposób dane publikacji wpisujemy tylko raz (do BPP), a ręczne ich wysyłanie do PBN nie jest potrzebne. -.. image:: images/admin/edycja_uczelnia/edycja_uczelnia_4.png +![image](images/admin/edycja_uczelnia/edycja_uczelnia_4.png) - -Obca jednostka --------------- +## Obca jednostka W systemie BPP powinna znajdować się jedna i wyłącznie jedna *Obca jednostka*. @@ -52,4 +46,7 @@ Jest to taka jednostka, do której trafiają autorzy, którzy afiliują na jedno Aby określić *Obcą jednostkę* należy wejść w module Redagowanie➡Struktura➡Uczelnie, wybrać nasza uczelnię i następnie wybrać jednostkę w polu *Obca jednostka* i zapisać taki rekord. -.. note:: warto, aby *Obca jednostka* miała odznaczone :ref:`Pole *Skupia pracowników*` oraz :ref:`Pole *Zarządzaj automatycznie*` +!!! note + + warto, aby *Obca jednostka* miała odznaczone [Pole *Skupia pracowników*](edycja_jednostka.md#pole-skupia-pracowników) oraz [Pole *Zarządzaj automatycznie*](edycja_jednostka.md#pole-zarządzaj-automatycznie) + diff --git a/docs/edycja_wydawnictwo.rst b/docs/edycja_wydawnictwo.md similarity index 50% rename from docs/edycja_wydawnictwo.rst rename to docs/edycja_wydawnictwo.md index 548d4097e..8029d74fc 100644 --- a/docs/edycja_wydawnictwo.rst +++ b/docs/edycja_wydawnictwo.md @@ -1,31 +1,22 @@ -Edycja danych rekordów - wydawnictwa zwarte, ciągłe, patenty, itp -================================================================= +# Edycja danych rekordów - wydawnictwa zwarte, ciągłe, patenty, itp -Dodawanie autorów do rekordów ------------------------------ +## Dodawanie autorów do rekordów Aby dodać autora do rekordu, podczas dodawania lub edycji nowego rekordu kliknij "Dodaj kolejne powiązanie autora z wyd. ciągłym / wyd. zwartym / patentem ...". -Zmiana kolejności autorów ------------------------------ +## Zmiana kolejności autorów Aby zmienić kolejność autorów, skorzystaj z przycisku przeciągania oraz techniki "przeciągnij i upuść". Po prostu kliknij i przytrzymaj lewym przyciskiem myszy na przycisku przeciągania i przeciągnij dane powiązanie autora z rekordem w górę lub w dół. Przycisk przeciągania wygląda w następujący sposób: -.. image:: images/editor/przycisk_przeciagania.png - :alt: Przycisk przeciągania +![Przycisk przeciągania](images/editor/przycisk_przeciagania.png) Możesz "zwinąć" formularz powiązania autora z rekordem aby zmiana kolejności autorów była łatwiejsza, co ma szczególne znaczenie na monitorach o niewielkiej rozdzielczości. -Działania te również prezentuje film `Zmiana kolejności autorów`_ . +Działania te również prezentuje film [Zmiana kolejności autorów](https://www.youtube.com/embed/oruEX3CykH8) . -.. raw:: html - - - - -.. _Zmiana kolejności autorów: https://www.youtube.com/embed/oruEX3CykH8 + diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 000000000..9fdd1744f --- /dev/null +++ b/docs/history.md @@ -0,0 +1,3862 @@ +# Historia zmian + +## bpp 202605.1372 (2026-05-04) + +### Naprawione + +- Naprawiono healthcheck lekkiego `authserver`-a, który zwracał + `503 Service Unavailable` przez `AttributeError` na nieistniejącym + `settings.CELERY_BROKER_URL`. Sonda Redis jest teraz pomijana, gdy + ustawienia nie konfigurują brokera Celery — `authserver` nie używa + kolejki zadań, więc jego stan zdrowia nie zależy od Redis-a. Sonda + PostgreSQL działa bez zmian. + +## bpp 202605.1371 (2026-05-04) + +### Naprawione + +- Batchowe enqueueowanie do PBN + (`queue_pbn_export_batch`) raportuje teraz nieoczekiwane + błędy do Rollbara i logów zamiast cicho je połykać. + Wcześniej blok `except Exception: pass` w pętli po + rekordach pochłaniał wszystkie wyjątki (DB error, + integrity error, programmer error) — pojedynczy zły + rekord nie zatrzymywał batcha, ale operator nie miał + żadnej widoczności co poszło nie tak. Brakujące rekordy + (`DoesNotExist`) i już-w-kolejce + (`AlreadyEnqueuedError`) nadal są pomijane bez alertu — + to nie są błędy. +- Endpoint `/health/` faktycznie sprawdza teraz dostępność + PostgreSQL (`SELECT 1`) i Redisa (`PING` z 2-sekundowym + timeoutem) i zwraca `503` z listą niedostępnych komponentów + zamiast bezwarunkowego `200 OK`. Docker healthcheck + serwisów `appserver` / `authserver` wykrywa teraz awarię + bazy lub brokera — wcześniej kontener pozostawał oznaczony + jako „healthy” mimo że strona nie była w stanie obsłużyć + żadnego requestu. +- Endpointy `/bpp/api/upload-punktacja-zrodla/`, + `/bpp/api/punktacja-zrodla/`, `/bpp/api/rok-habilitacji/`, + `/bpp/api/ostatnia-jednostka-i-dyscyplina/` oraz + `/bpp/api/pubmed-id/` wymagają teraz zalogowania. + Wcześniej były `csrf_exempt` bez sprawdzania + uwierzytelnienia — w szczególności + `upload-punktacja-zrodla` przyjmował anonimowe POST-y + i tworzył wpisy `Punktacja_Zrodla` w bazie. Adminowy JS + nadal działa bez zmian (sesja zalogowanego użytkownika); + zmiana blokuje wyłącznie wywołania nieautoryzowane. +- Naprawiono auto-uzupełnianie jednostki i dyscypliny przy dodawaniu + autora w publicznym formularzu „Zgłoś publikację”. Skrypt + `autorform_dependant.js` wysyłał POST do + `/bpp/api/ostatnia-jednostka-i-dyscyplina/` bez tokenu CSRF — + publiczne `base.html` (w przeciwieństwie do admin-owego) nie ma + globalnego `$.ajaxSetup` dodającego nagłówek `X-CSRFToken`, + więc żądanie kończyło się odpowiedzią 403 i pola nie były + wypełniane. Skrypt czyta teraz `csrfmiddlewaretoken` z ukrytego + pola formularza i dokleja go do danych żądania. +- Strony przeglądania `/bpp/browse/autorzy/`, + `/bpp/browse/zrodla/` i `/bpp/browse/jednostki/` + generują listę aktywnych literek alfabetu jednym zapytaniem + `SELECT DISTINCT` zamiast 26+ osobnych `EXISTS`-ów + (po jednym na każdą literkę z osobnym matchingiem dla + polskich znaków). Polskie diakrytyki nadal mapują się na + kanoniczne litery (`Ą` → `A`, `Ł` → `L` itd.). +- Task `pbn_downloader_app.tasks.download_institution_publications` + nie wykonuje już redundantnego sprawdzenia stanu + „running” poza transakcją. Atomowy check-and-create + w `create_task_with_lock` nadal zapobiega duplikatom; + usunięcie wcześniejszego, nie-atomowego check-a likwiduje + race-window, w którym dwa workery przechodziły check, oba + otrzymywały `ValueError` w wyścigu o lock i jeden niepotrzebnie + failował zamiast po prostu czekać. +- Taski importu dyscyplin (`stworz_kolumny`, + `przeanalizuj_import_dyscyplin`, + `integruj_import_dyscyplin`) faktycznie ryglują rekord + `Import_Dyscyplin` przez `SELECT ... FOR UPDATE`. + Wcześniej wywołanie `select_for_update().filter(pk=pk)` + zwracało leniwy `QuerySet`, który nigdy nie był ewaluowany — + SQL z klauzulą `FOR UPDATE` nie szedł do bazy, a lock + realnie nie istniał. Przy równoczesnym przetwarzaniu tego + samego importu (np. user kliknie „Przeanalizuj” dwa razy + pod rząd) workery mogły deptać sobie po polach FSM. +- `test_health_check_returns_503_when_db_down` zatruwał blocker + `pytest-django` dla całego workera xdist (`monkeypatch.setattr` na + `ConnectionProxy` wstrzykiwał bound `_blocking_wrapper` do + `connections[default].__dict__`, co nadpisywało class-level patch + i czyniło `django_db_blocker.unblock()` bezskutecznym). Multiseek + testy padały deterministycznie 50 errors w `setup_databases`. + Patch zmieniony na `health._check_db` (symetrycznie do testu + redis-down). Dodatkowo middleware `test_logging_*` w + `test_page_validation.py` zyskały autouse fixture wpinający + `caplog.handler` bezpośrednio do loggera `django.request` — + po zmianie `propagate=False` z commita audytu caplog nie widział + WARNING-ów o zablokowanych żądaniach. + +### Usprawnienie + +- Admin interface dla aplikacji `importer_publikacji`: superuser może + przeglądać historię importu publikacji (model `ImportSession` z + oryginalnym tekstem BibTeX w polu `raw_data`) oraz dopasowanych + autorów (model `ImportedAuthor`). Obie klasy zarejestrowane w + Django adminie jako read-only (bez możliwości ręcznego tworzenia + lub edycji, podgląd tylko). Lista sesji wspiera filtrowanie po statusie, + dostawcy, dacie i autorach; wyszukiwanie po identyfikatorze, tytule, + DOI; szczegóły sesji pokazują sformatowane JSON `raw_data`, + `normalized_data`, `matched_data` oraz tabelę autorów z + linkami do dopasowanych obiektów BPP. + +- Deduplikator autorów: gruntowna przebudowa UI. Tytuł i pozycje + menu uproszczone z "Deduplikator autorów PBN" na "Deduplikator + autorów" (bez znacznika BETA), wpis dodany dodatkowo do podmenu + "Operacje". Tryb skanowania (PBN/ogólny) prezentowany jest jako + kolorowy badge przy "Główny rekord autora", filtr "Pokaż wyniki" + zmieniony z radio-buttonów na poziomy button-group. + + Przyciski na karcie każdego potencjalnego duplikatu pogrupowane + w trzy logiczne sekcje: Podgląd (otwórz wyd. ciągłe/zwarte, + redagowanie, stronę główną, PBN), Decyzja ("Nie jest duplikatem + głównego autora", usuń autora bez publikacji), Scalanie (cztery + warianty scalania). Przyciski "Scal + ustaw dyscyplinę" oraz + "Scal + ustaw subdyscyplinę" są ukryte, gdy główny autor nie ma + żadnej dyscypliny. + + Powody podobieństwa renderowane są jako kolorowe chipy z ikonami + Foundation, z tonami match/info/weak/warn dobranymi do siły + przesłanki. Procent pewności jest sklampowany do zakresu 0–100% + (wcześniej widoczne były wartości typu 140% wynikające z surowego + score). + + Naprawione: oznaczenie autora jako nie-duplikat (przycisk + "Nie jest duplikatem głównego autora") wykonuje się teraz przez + AJAX z fadeOut karty, zamiast przeładowywać widok i przeskakiwać + do kolejnego głównego autora. Naprawiono też "Scal wszystkie", + który dla kandydatów z trybu ogólnego zwracał błąd 400 (JS + wysyłał `main_scientist_id` zamiast `main_autor_id`); brakujące + parametry trafiają teraz dodatkowo do Rollbara. + +- Deduplikator autorów: nowy tryb "ogólny" znajdujący duplikaty wśród + autorów spoza listy pracowników instytucji w PBN. Jeden przycisk + "Skanuj duplikaty" uruchamia obie fazy (PBN + ogólna) sekwencyjnie. + Widok pozwala filtrować wyniki radio-button-em (PBN/Ogólny/Oba), + eksport XLSX zawiera kolumnę "Tryb". Anulowanie fazy ogólnej skutkuje + statusem "Częściowo zakończone" — wyniki PBN pozostają dostępne. + +- Formularz zgłaszania publikacji: pomocniczy tekst pola „Link do publikacji + lub DOI" jest teraz dobierany w zależności od kombinacji rodzaju publikacji + i formy dostępu — m.in. fragment o katalogach BN/NUKAT pojawia się tylko + przy monografii i rozdziale w dostępie ograniczonym, a wzmianka o PBN + znika dla publikacji typu „Inne". Dla rodzaju „Inne" pole nie jest + wymagane (ponieważ tych publikacji nie wysyłamy do PBN); dla dostępu + ograniczonego pozostaje wymagany plik PDF. + +- Logi backendu Django zawierają teraz timestamp w formacie + ISO oraz nazwę loggera, co pozwala korelować zdarzenia + między równoczesnymi workerami w produkcji bez polegania + wyłącznie na timestampach z `systemd` / Celery. Domyślnie + skonfigurowane są też loggery `django.security` + (SuspiciousOperation, DisallowedHost, niewłaściwy CSRF token), + `django.request` (4xx/5xx requestów) i `celery` + (retry, ack, errors). Dotychczasowy logger `pbn_import` + zachowuje swój dawny czysty format (bez timestampu) na + potrzeby UI pełnotekstowego importu. + +- Polecenie `manage.py run_site` strumieniuje teraz logi + runservera, celery i PostgreSQL równocześnie do jednego + terminala z kolorowymi prefiksami (`web`, `celery`, `pg`) + — jak `docker compose up`. Linie z różnych procesów są + serializowane przez wątkowy multiplekser, więc się nie sklejają. + Dodatkowo na lokalnym dev-stacku z `run_site` cookie banner + jest automatycznie ukrywany — endpoint auto-loginu ustawia + cookie `cookielaw_accepted=1` w odpowiedzi z przekierowaniem, + co przy zwyczajowym workflow (uruchom `run_site` → przeglądarka + otwiera autologin → przekierowanie na `/`) eliminuje banner. + +- Task `zaktualizuj_liczbe_cytowan` (pobieranie liczby + cytowań z Web of Science) używa teraz + `celery_singleton.Singleton` z 2-godzinnym lockiem + w Redisie i `time_limit=2h`. Dwa równoczesne uruchomienia + (np. ręczne kliknięcie + zaplanowany cron) nie odpytają już + zewnętrznego API podwójnie, a zawieszony WoS request + nie zablokuje workera w nieskończoność. + +- `manage.py run_site` zapisuje teraz numer portu runservera do + gitignored pliku `.run_site_port` (analogicznie do + `.run_site_token`). Agent kodujący nie musi już parsować bannera + ani logów — składa URL z `cat .run_site_port` + `cat .run_site_token`. Plik jest ulotny: kasowany na exit run_site. + +- `manage.py run_site` zapisuje teraz porty PostgreSQL i Redis-a + (testcontainers) do gitignored plików `.run_site_pg_port` i + `.run_site_redis_port` (analogicznie do `.run_site_port`). Agent + kodujący może podpiąć `psql` / `redis-cli` bez parsowania bannera + — w stdoucie banner zawiera teraz gotowe snippety dla obu narzędzi. + Pliki są ulotne: kasowane na exit run_site. + +### Usunięto + +- Usunięto pozostałości po niezainstalowanej integracji + Sentry: moduł `django_bpp.sentry_support`, jego test, + endpoint `/sentry_test/` oraz sekcja `SENTRYSDK_*` + w `.env.example`. Projekt używa Rollbara — żadne + ustawienie Sentry nie było aktywne, a artefakty wprowadzały + w błąd. Endpointy `/test_403/`, `/test_500/` + i `/test_exception/` (do podglądu stron błędów i + weryfikacji integracji Rollbara) pozostają. + + Z `package.json` usunięto pakiet `font-awesome 4.1.0` + (nie był importowany przez bundle ani template'y; biblioteka + po EOL z dostępnymi CVE). Aktywnie używany `jqueryui 1.11.1` + zostaje — wymiana wymaga osobnej, większej zmiany. + + Z `bpp/tasks.py` usunięto martwą funkcję `my_limit()` + i moduł-globalny słownik `task_limits` — funkcja nie była + nigdzie wywoływana, a per-procesowy słownik nie miał szans + działać poprawnie z wieloma workerami. + +## bpp 202605.1370 (2026-05-02) + +### Naprawione + +- Importer publikacji wywalał się z `TypeError: '>' not supported between instances of 'NoneType' and 'int'` przy próbie utworzenia rekordu, gdy + dane źródłowe (np. BibTeX) nie zawierały roku publikacji. Po stronie + `ISlot` dodano obsługę `rok=None` (zwracane jest `CannotAdapt`, + sloty nie są liczone), a w samym imporcie `_create_publication` + waliduje obecność roku i zgłasza czytelny komunikat zamiast pełnego + tracebacku. +- Naprawa testów Playwright (Chromium) padających na CI od commit-a `bafd8f209` (session-scoped `channels_live_server`). Daphne subprocess fork-uje z pytest worker process-u i dziedziczy monkey-patch `pytest_django._blocking_wrapper` na `BaseDatabaseWrapper.ensure_connection`, przez co każde zapytanie do DB w middleware (`django_countdown`, `bpp_setup_wizard`) crashowało z `RuntimeError: Database access not allowed` → 500 → puste strony → timeout-y Playwright. Fix: `set_database_connection` w subprocesie Daphne przywraca oryginalną implementację `ensure_connection`. + +### Usprawnienie + +- Dodano polecenia `dump_pbn_token` i `load_pbn_token` do + przenoszenia tokenu PBN użytkownika między instancjami BPP — bez + zrzutu całej bazy. `dump_pbn_token --user=` wypisuje JSON + z tokenem i datą jego ostatniej aktualizacji na stdout, a + `load_pbn_token --user=` czyta ten JSON ze stdin i ustawia + te same wartości lokalnemu użytkownikowi. + + W `run_site` dodano flagę `--get-pbn-token-from USERNAME@SSH-HOST`, która automatyzuje ten transfer — łączy się po + SSH ze wskazanym hostem (alias z `~/.ssh/config`), uruchamia + `dump_pbn_token` w kontenerze `appserver` z katalogu + `bpp-deploy` i wynik wgrywa do lokalnej bazy. Domyślne ścieżki i + nazwę serwisu można nadpisać flagami `--remote-deploy-path` i + `--remote-compose-service`. + +- Nowa komenda `manage.py run_site` — uruchamia dev stack BPP w testcontainerach + na losowych portach (PG + Redis), opcjonalnie odtwarza dump bazy + (`--from-dump path`, autodetect `.sql` / `.sql.gz` / `.dump`), tworzy + superusera `admin/admin`, odpala `runserver` i otwiera przeglądarkę. + Eliminuje konflikty portów przy wielu konfiguracjach BPP na jednym serwerze. + +## bpp 202604.1369 (2026-04-28) + +### Naprawione + +- Naprawiono generowanie `src/baseline-sql/baseline.sql`: komenda + `baseline_rebuild` uruchamia teraz `pg_dump` *wewnątrz* + testcontenera (`docker exec`) zamiast używać klienta z hosta. + Gdy host miał nowszy major PostgreSQL niż obraz bazowy + (`iplweb/bpp_dbserver:psql-16.13`), `pg_dump` w wersji 17 + wstawiał do dumpa dyrektywę `SET transaction_timeout = 0;`, + której PostgreSQL 16 nie zna — przez co odtworzenie baseline'u + na docelowej wersji się wywalało. Klient i serwer są teraz + zawsze w tym samym majorze. Dodatkowo scrubber wycina takie + linie jako safety net na wypadek przyszłych nowych dyrektyw. +- Naprawiono komunikat o przeterminowanym haśle, który pojawiał się + użytkownikom zalogowanym przez Microsoft (`microsoft_auth`) lub + ORCID (`orcid_integration`) bez formularza zmiany hasła. Hasłem + takich kont zarządza zewnętrzny IdP, więc polityka wygasania nie + powinna ich w ogóle obejmować — middleware + `ConditionalPasswordChangeMiddleware` już to respektował, ale + context processor `password_status` z `django-password-policies` + nadal sprawdzał wiek hasła w bazie i ustawiał + `password_change_required = True` w kontekście szablonu, przez co + `base.html` renderował callout bez formularza (zmienna `form` + istnieje tylko w widoku zmiany hasła, do którego middleware słusznie + nie przekierowywał). Dodano + `django_bpp.context_processors.conditional_password_status`, + który symetrycznie pomija sprawdzenie dla backendów OAuth z + `EXTERNAL_AUTH_BACKENDS` i deleguje do oryginalnego context + processora wyłącznie dla zwykłego logowania `ModelBackend`. + +### Usprawnienie + +- CI: shardy `pytest` w workflow `Tests` nie odpalają już `make assets` przy starcie. Obraz `test-runner` ma zapieczone CSS i `.mo` + z buildu obrazu (stage `test-runner` w `docker/bpp_base/Dockerfile`), + więc `conftest.py` honoruje teraz zmienną `BPP_SKIP_ASSETS_BUILD=1` + ustawioną w `docker-compose.test.ci.yml`. + + Wcześniej każdy z ośmiu równoległych shardów wpadał w + `pytest_configure` i — z powodu braku sentinela + `node_modules/.installed` w obrazie — odpalał pełny `yarn install` + + `grunt build` przed pierwszym testem. Lokalny dev nie jest zmieniony: + bez tej zmiennej `conftest.py` nadal uruchamia `make assets` jako + safety net. + +- Pipeline release-u (`make new-release` oraz `make release`) + weryfikuje teraz zaleznosci pod katem znanych CVE PRZED zbumpieniem + wersji i wystartowaniem builda. Nowy target `make scan-deps` + generuje SBOM (CycloneDX) z `uv.lock` przez `uv export --no-dev` + i puszcza go przez OSV-Scanner, Grype oraz Trivy. Jezeli ktorykolwiek + skaner znajdzie HIGH/CRITICAL CVE, `make` zatrzyma sie z exit 1 i + release nie ruszy — zeby pominac (na wlasna odpowiedzialnosc), uzyj + `./bin/scan-deps.sh --no-gate`. Wymagane narzedzia: `brew install osv-scanner grype trivy`. + + Workflow `dependency-audit.yml` rozszerzony o drugi job + `multi-scanner`, ktory na CI generuje ten sam SBOM i odpala te + same trzy skanery jako defense-in-depth obok istniejacego gate-u + `uv-secure`. Nowe skanery sa report-only (zapisuja markdown do + `GITHUB_STEP_SUMMARY`, nie blokuja merga) — chodzi o widocznosc + findings, ktorych nie wykryla baza `uv-secure`, bez ryzyka + zablokowania PR-a falszywym pozytywem z innej bazy CVE. + +## bpp 202604.1368 (2026-04-28) + +### Naprawione + +- Naprawiono migrację `0413_bppuser_autor_onetoone`, która kończyła + się błędem `cannot ALTER TABLE "bpp_bppuser" because it has pending trigger events` na bazach z istniejącymi danymi. Migracja została + oznaczona jako nieatomowa, dzięki czemu deferred triggery (`denorm`) + odpalane przez `RunPython` wystrzeliwują przed kolejnymi + `ALTER TABLE` na tej samej tabeli. + +## bpp 202604.1367 (2026-04-28) + +### Naprawione + +- `MaliciousRequestBlockingMiddleware` blokował legalne żądania + DataTables AJAX, jeśli tabela miała wiele kolumn — biblioteka + serializuje per-kolumnowe metadane (`columns[N][data]`, + `[search][value]`, …) do query stringu, który łatwo przekraczał + limit 2048 znaków. Konsekwencja: kontrolki DataTables na widokach + `/api/...` zwracały HTTP 444 zamiast danych, a integracyjne testy + Playwright (m.in. `import_dyscyplin`) timeout'owały się czekając + na dane, których serwer odmówił. + + Dwie zmiany: + + - Limit `MAX_FULL_PATH_LENGTH` podniesiony 2048 → 4096 znaków + (mieści typowy DataTables-payload bez otwierania drzwi rekurencyjnym + `?next=` od skanerów, bo te i tak obsługuje osobny check). + - Ścieżki zawierające `/api/` są zwolnione z check'u długości pełnego + URL — endpointy API legalnie generują wzdęte query stringi, a + scanner-boty z rekurencyjnymi przekierowaniami i tak nie kierują + swoich łańcuchów na `/api/`. (middleware-api-whitelist) + +- Pełen suite testów Playwright zostaje przyspieszony z ~3:50 do ~2:24 + (−85 s, −38 %) bez utraty pokrycia. + + Główne źródło zysku — naprawa ukrytego buga w + `django_bpp.playwright_util.select_select2_autocomplete`: pierwszy + `wait_for_selector` na `#select2-{id}-container` trafiał w pełen + 30-sekundowy timeout w testach gdzie ten wariant markupu nie istnieje + (formularze inline django-grappelli admin), zanim wpadał do bloku + `except` z fallbackowym selektorem siostrzanym. Helper jest używany + w 64 miejscach — każde wywołanie traciło ~30 s. Najwolniejsze testy + jak `test_changeform_add_full_flow` (3 wywołania select2) traciły + ~90 s na samych timeoutach. + + Naprawa: race obu selektorów przez listę `", "` w jednym + `wait_for_selector` — zwracamy się do `.select2-selection` (zawsze + klikalny element) zamiast container'a. Efekt: + + - `test_changeform_add_full_flow`: 97 s → 8 s + - `test_admin_wydawnictwo_ciagle_dowolnie_zapisane_nazwisko`: + 67 s → 8 s + - `test_procent_odpowiedzialnosci_*_dwoch_autorow` cluster: + 37–48 s → 12–18 s + + Drugi front — eliminacja antywzorców `wait_for_load_state(networkidle)` + i sztywnych `wait_for_timeout()` w testach Playwright, zastępowane + warunkowymi waitami (`expect(...).to_have_value()`, + `page.expect_navigation`, polling DB/listy dialogów): + + - `test_integracyjny` (import dyscyplin): 75 s → 13 s — usunięte + sztywne sleepy i `networkidle` na stronie z otwartym WebSocketem + - `test_multiseek_*` (6 testów): 30+ s → ~2 s — `expect_navigation` + zamiast `networkidle` po klikach search + - `test_smoke` crawler: usunięty `networkidle` w pętli (zawsze + trafiał w 10 s timeout bo strony BPP mają long-polling) + - `test_toz_tamze`, `test_admin_forms`, `test_clarivate`, + `test_change_form_pbn_isbn_doi_etc`, `test_change_form_pubmed`, + `test_crossref_api_sync_playwright` — sztywne `wait_for_timeout` + zamienione na polling licznika rekordów / listy dialogów / wartości + pól; w przypadku dialog handlerów polling musi pompować event loop + przez `page.wait_for_timeout` (a nie `time.sleep`), bo handler + odpala się tylko gdy Playwright przetwarza eventy. (playwright-suite-speedup) + +- Naprawiono blokowanie zapytań AJAX widgetów DataTables przez + `MaliciousRequestBlockingMiddleware`. Limit długości pełnego URL-a + (`MAX_FULL_PATH_LENGTH`) został podniesiony z 2048 na 8192 — DataTables + przy ~10 kolumnach generuje query string z percent-encoded metadanymi + kolumn (`columns%5B0%5D%5Bdata%5D=…`) przekraczający 2 KB, ale dobrze + mieszczący się w 8 KB (zgodnie z domyślnym `large_client_header_buffers` + nginxa i `LimitRequestLine` Apacha). Eksponencjalnie rosnące łańcuchy + `?next=` produkowane przez bot-skannery nadal są łapane — albo przez + nowy próg, albo przez detektor zagnieżdżonego `?next=`. + +- Naprawiono błąd teardown testów `TransactionTestCase` (m.in. testów + Playwright z `transaction=True`) — `TRUNCATE` Django flush'a wywalał + się na FK z niezarządzanej tabeli `bpp_rekord_mat` do zarządzanej + `bpp_charakter_formalny`. Monkey-patch `_fixture_teardown` (dodający + `allow_cascade=True` i retry przy deadlocku) został przeniesiony z + `src/fixtures/conftest.py` do `src/conftest.py`: ten pierwszy plik + jest siostrzanym katalogiem względem testów i pytest go automatycznie + NIE ładuje dla testów spoza `src/fixtures/`, więc patch nigdy nie + zaczepiał się dla większości testów transakcyjnych. + +- Naprawiono losowe failowanie kilku testów Playwrighta uruchamianych + równolegle z `-n auto`. Testy używające session-scoped fixture + `channels_live_server` (jeden Daphne na worker, reuse między + testami) były wrażliwe na pollution stanu w shared ASGI procesie: + wycieki konekcji DB i race między test'em a serwerem na widoczność + commitowanych danych. + + Dodano function-scoped warianty `admin_page_per_test` i + `preauth_asgi_page_per_test` (oparte o istniejący + `channels_live_server_per_test`) — każdy test dostaje świeży + proces Daphne. Przepięto na nie testy: + + - `test_bpp_notifications` + - `test_global_search_logged_in` + - `test_procent_odpowiedzialnosci_baseModel_AutorFormset_jeden_autor` + - `test_procent_odpowiedzialnosci_baseModel_AutorFormset_dwoch_autorow` + - `test_procent_odpowiedzialnosci_baseModel_AutorFormset_dobrze_potem_zle_dwoch_autorow` + + Pozostałe testy (~67) nadal używają szybkiego session-scoped + `channels_live_server` — bez regresji wydajności. + +## bpp 202604.1366 (2026-04-27) + +### Naprawione + +- Rozszerzono `MaliciousRequestBlockingMiddleware` o dwie dodatkowe + heurystyki ograniczające szum w logach od skanerów bezpieczeństwa: + + - Pełny URL (ścieżka + query string) dłuższy niż 2048 znaków zwraca + HTTP 444. Dotychczasowy limit 1024 znaków obejmował tylko + `request.path` i przepuszczał wzdęte query stringi. + - Parametr `next=` zawierający kolejne `?next=` (po dekodowaniu + query stringu przez Django) jest blokowany jako odcisk bota + podążającego za przekierowaniami logowania bez cookies — typowy + wzorzec rekurencyjnie zakodowanych łańcuchów krążących między + `/accounts/login/` a `/admin/login/`. + + Pojedynczy, prawidłowy `next=` (np. po nieautoryzowanej próbie + wejścia do widoku `toz`) pozostaje dozwolony. (blokada-zagnezdzonych-next) + +- Naprawiono renderowanie paginacji w widokach z HTMX (np. `/pbn_export_queue/`), + gdzie stopka strony lądowała pomiędzy pagerem a tabelą. Przyczyną była + minifikacja HTML aplikowana do fragmentów ładowanych przez + `hx-swap="innerHTML"` — `minify-html` zaprojektowany dla pełnych + dokumentów restrukturyzował niezamknięte/puste tagi (m.in. pusty + `
  • `) w partial-ach, rozjeżdżając DOM po wstawieniu. + + Wprowadzono prewencję systemową przeciwko regresjom tej klasy: + + - `BppMinifyHtmlMiddleware` omija minifikację gdy żądanie ma nagłówek + `HX-Request: true` (wszystkie HTMX-owe partial-e bypassują minifier). + - Linter `djlint` dodany do pre-commit z aktywnymi regułami + strukturalnymi (H020 puste-tag-pair, H025 orphan-tag) — wykrywa + podobne pułapki przed merge-em. + - Test integralności `test_html_minify_integrity.py` weryfikuje że + typowe trefne wzorce (puste `
  • `, `

    `, ``) po + minifikacji nie rozjeżdżają struktury DOM, plus że HTMX-owe requesty + są właściwie bypassowane. + + Dodatkowo style paginacji `pagination_with_anchor.html` przeniesione z + inline `