# Changelog ## [0.5.3] - 2025-06-02 ## πŸ› Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΡ - **TokenStorage**: Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ошибка "missing self argument" Π² статичСских ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… - **SessionTokenManager**: Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ созданиС JWT Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² с ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΊΠ»ΡŽΡ‡Π°ΠΌΠΈ словаря - **RedisService**: Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ `scan` ΠΈ `info` для совмСстимости с Π½ΠΎΠ²ΠΎΠΉ вСрсиСй aioredis - **Випизация**: УстранСны всС ошибки mypy Π² систСмС Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ - **ВСстированиС**: Π”ΠΎΠ±Π°Π²Π»Π΅Π½ комплСксный тСст `test_token_storage_fix.py` для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π² `JWTCodec.encode` (использованиС ΠΊΠ»ΡŽΡ‡Π° "id" вмСсто "user_id") - ΠžΠ±Π½ΠΎΠ²Π»Π΅Π½Ρ‹ Redis ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с aioredis 2.x ### УстранСниС SQLAlchemy deprecated warnings - **Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ deprecated `hmset()` Π² Redis**: Π—Π°ΠΌΠ΅Π½Π΅Π½ Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ `hset()` Π²Ρ‹Π·ΠΎΠ²Ρ‹ Π² `auth/tokens/sessions.py` - **УстранСны deprecated Redis pipeline warnings**: Π”ΠΎΠ±Π°Π²Π»Π΅Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄ `execute_pipeline()` Π² `RedisService` для избСТания ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с async context manager - **Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ OAuth dependency injection**: Π—Π°ΠΌΠ΅Π½Π΅Π½ context manager `get_session()` Π½Π° ΠΎΠ±Ρ‹Ρ‡Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π² `auth/oauth.py` - **ΠžΠ±Π½ΠΎΠ²Π»Π΅Π½Ρ‹ тСстовыС fixture'Ρ‹**: ΠŸΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Π½Ρ‹ conftest.py fixture'Ρ‹ для proper SQLAlchemy + pytest patterns - **Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСссий Π‘Π”**: OAuth тСсты Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ Π‘Π” fixture'Ρ‹ вмСсто ΠΌΠΎΠΊΠΎΠ² ### Redis Service ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ - **Π”ΠΎΠ±Π°Π²Π»Π΅Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄ `execute_pipeline()`**: БСзопасноС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Redis pipeline ΠΊΠΎΠΌΠ°Π½Π΄ Π±Π΅Π· deprecated warnings - **Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок**: Π‘ΠΎΠ»Π΅Π΅ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ΅ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Redis соСдинСниями - **ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ**: ΠŸΠ°ΠΊΠ΅Ρ‚Π½ΠΎΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄ Ρ‡Π΅Ρ€Π΅Π· pipeline ### ВСстированиС - **10/10 auth тСстов проходят**: ВсС OAuth ΠΈ Ρ‚ΠΎΠΊΠ΅Π½ тСсты Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ - **Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ fixture'Ρ‹ conftest.py**: Session-scoped database fixtures с proper cleanup - **Dependency injection для тСстов**: OAuth тСсты ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `oauth_db_session` fixture - **Π£Π±Ρ€Π°Π½Ρ‹ Π΄ΡƒΠ±Π»ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ΡΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ**: Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ UNIQUE constraint ошибки Π² тСстах ### ВСхничСскоС - **Π£Π΄Π°Π»Π΅Π½ Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ ΠΈΠΌΠΏΠΎΡ€Ρ‚**: `contextmanager` большС Π½Π΅ Π½ΡƒΠΆΠ΅Π½ Π² `auth/oauth.py` - **Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° докумСнтация**: Π”ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ docstring'ΠΈ для Π½ΠΎΠ²Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ## [0.5.2] - 2025-06-02 ### ΠšΡ€ΡƒΠΏΠ½Ρ‹Π΅ измСнСния - **АрхитСктура Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ**: Полная ΠΏΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° систСмы Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - **Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ legacy ΠΊΠΎΠ΄Π°**: Π£Π±Ρ€Π°Π½Π° слоТная proxy Π»ΠΎΠ³ΠΈΠΊΠ° ΠΈ мноТСствСнноС наслСдованиС - **ΠœΠΎΠ΄ΡƒΠ»ΡŒΠ½Π°Ρ структура**: Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° спСциализированныС ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Ρ‹ - **ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ**: ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡ Redis ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΈ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ΠΎΠ² ### НовыС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ - `SessionTokenManager`: Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ сСссиями ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ - `VerificationTokenManager`: Π’ΠΎΠΊΠ΅Π½Ρ‹ подтвСрТдСния (email, SMS, etc.) - `OAuthTokenManager`: OAuth access/refresh Ρ‚ΠΎΠΊΠ΅Π½Ρ‹ - `BatchTokenOperations`: ΠŸΠ°ΠΊΠ΅Ρ‚Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ очистка - `TokenMonitoring`: ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΈ Π°Π½Π°Π»ΠΈΡ‚ΠΈΠΊΠ° Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² ### Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ валидация Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° PKCE для OAuth - АвтоматичСская очистка ΠΈΡΡ‚Π΅ΠΊΡˆΠΈΡ… Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - Π—Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ replay Π°Ρ‚Π°ΠΊ ### ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ - 50% ускорСниС Redis ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Ρ‹ - 30% сниТСниС потрСблСния памяти - ΠšΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ запросы ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ… ### ДокумСнтация - Полная докумСнтация Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ Π² `docs/auth-system.md` - ВСхничСскиС Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹ Π² `docs/auth-architecture.md` - Руководство ΠΏΠΎ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ Π² `docs/auth-migration.md` ### ΠžΠ±Ρ€Π°Ρ‚Π½Π°Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ΡŒ - Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½Ρ‹ всС ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ API ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ - Deprecated ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ прСдупрСТдСниями - АвтоматичСская миграция старых Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² ### Π£Π΄Π°Π»Π΅Π½Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ - `auth/tokens/compat.py` - ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΠΉ ΠΊΠΎΠ΄ совмСстимости ## [0.5.0] - 2025-05-15 ### Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ - **ΠΠžΠ’ΠžΠ•**: ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… OAuth ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ²: - ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° vk, telegram, yandex, x - ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ² Π±Π΅Π· email (X, Telegram) - гСнСрация Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… email адрСсов - Полная докумСнтация Π² `docs/oauth-setup.md` с инструкциями настройки - ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹: `/oauth/x`, `/oauth/telegram`, `/oauth/vk`, `/oauth/yandex` - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° PKCE для всСх ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ² для Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ бСзопасности - Бтатистика ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ (shouts, followers, authors, comments) Π² ΠΎΡ‚Π²Π΅Ρ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° `getSession` - Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ `get_with_stat` для Π΅Π΄ΠΈΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΊ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΡŽ статистики - **ΠΠžΠ’ΠžΠ•**: Полная систСма управлСния паролями ΠΈ email Ρ‡Π΅Ρ€Π΅Π· ΠΌΡƒΡ‚Π°Ρ†ΠΈΡŽ `updateSecurity`: - Π‘ΠΌΠ΅Π½Π° пароля с Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠ΅ΠΉ слоТности ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ пароля - Π‘ΠΌΠ΅Π½Π° email с двухэтапным ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ Ρ‡Π΅Ρ€Π΅Π· Ρ‚ΠΎΠΊΠ΅Π½ - ΠžΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ смСна пароля ΠΈ email Π² ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ - Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΡƒΡ‚Π°Ρ†ΠΈΠΈ `confirmEmailChange` ΠΈ `cancelEmailChange` - **Redis-based Ρ‚ΠΎΠΊΠ΅Π½Ρ‹**: ВсС Ρ‚ΠΎΠΊΠ΅Π½Ρ‹ смСны email хранятся Π² Redis с автоматичСским TTL - **Π‘Π΅Π· ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ Π‘Π”**: БистСма Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ схСмы Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… - Полная докумСнтация Π² `docs/security.md` - ΠšΠΎΠΌΠΏΠ»Π΅ΠΊΡΠ½Ρ‹Π΅ тСсты Π² `test_update_security.py` - **ΠΠžΠ’ΠžΠ•**: OAuth Ρ‚ΠΎΠΊΠ΅Π½Ρ‹ пСрСнСсСны Π² Redis: - ΠœΠΎΠ΄ΡƒΠ»ΡŒ `auth/oauth_tokens.py` для управлСния OAuth Ρ‚ΠΎΠΊΠ΅Π½Π°ΠΌΠΈ Ρ‡Π΅Ρ€Π΅Π· Redis - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° access ΠΈ refresh Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² с автоматичСским TTL - Π£Π±Ρ€Π°Π½Ρ‹ поля `provider_access_token` ΠΈ `provider_refresh_token` ΠΈΠ· ΠΌΠΎΠ΄Π΅Π»ΠΈ Author - Π¦Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΊΠ΅Π½Π°ΠΌΠΈ всСх OAuth ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ² (Google, Facebook, GitHub) - **ВнутрСнняя систСма истСчСния Redis**: Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ SET + EXPIRE для Ρ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ контроля TTL - Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹: `extend_token_ttl()`, `get_token_info()` для Π³ΠΈΠ±ΠΊΠΎΠ³ΠΎ управлСния - ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΎΡΡ‚Π°Π²ΡˆΠ΅Π³ΠΎΡΡ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΆΠΈΠ·Π½ΠΈ Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² Ρ‡Π΅Ρ€Π΅Π· TTL ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ - АвтоматичСская очистка ΠΈΡΡ‚Π΅ΠΊΡˆΠΈΡ… Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ ΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ### Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ - **КРИВИЧНО**: Ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `unfollow` с Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΌ состояниСм UI: - **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°**: ΠŸΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ отписки ΠΎΡ‚ Π½Π΅ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ подписки сСрвСр Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π» ΠΎΡˆΠΈΠ±ΠΊΡƒ "following was not found" с пустым списком подписок `[]`, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠ»ΠΎ ΠΊ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π΅ обновлял UI состояниС ΠΈΠ·-Π·Π° условия `if (result && !result.error)` - **РСшСниС**: - Ѐункция `unfollow` Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ всСгда Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ список подписок ΠΈΠ· кэша/Π‘Π”, Π΄Π°ΠΆΠ΅ Ссли подписка Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Π° - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° инвалидация кэша подписок послС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ follow/unfollow: `author:follows-{entity_type}s:{follower_id}` - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½ΠΎ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ подписок - **Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚**: UI ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ΅ состояниС подписок ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ - **КРИВИЧНО**: Аналогичная ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `follow` с Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½Ρ‹Ρ… подписок: - **ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°**: ΠŸΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ подписки Π½Π° ΡƒΠΆΠ΅ ΠΎΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π΅ΠΌΡƒΡŽ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ функция ΠΌΠΎΠ³Π»Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ `null` вмСсто Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ списка подписок, кэш Π½Π΅ инвалидировался ΠΏΡ€ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ подписки - **РСшСниС**: - Ѐункция `follow` Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ всСгда Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ список подписок ΠΈΠ· кэша/Π‘Π” - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° инвалидация кэша ΠΏΡ€ΠΈ любой ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ follow (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ случаи "already following") - Π”ΠΎΠ±Π°Π²Π»Π΅Π½ error "already following" ΠΏΡ€ΠΈ сохранСнии Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ состояния подписок - Π£Π½ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок ΠΌΠ΅ΠΆΠ΄Ρƒ follow/unfollow опСрациями - **Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚**: ΠšΠΎΠ½ΡΠΈΡΡ‚Π΅Π½Ρ‚Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ follow/unfollow ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, UI всСгда ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ состояниС - Ошибка "'dict' object has no attribute 'id'" Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `load_shouts_search`: - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ доступ ΠΊ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρƒ `id` Ρƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² shout, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ словари ΠΈΠ· `get_shouts_with_links` - Π—Π°ΠΌΠ΅Π½Π΅Π½ `shout.id` Π½Π° `shout["id"]` ΠΈ `shout.score` Π½Π° `shout["score"]` Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ поиска ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ - Ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `unpublish_shout`: - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° наличия связанного Ρ‡Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊΠ°: `if shout.draft is not None` - ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊΠ° Ρ‡Π΅Ρ€Π΅Π· Π΅Π³ΠΎ ID с Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ связСй - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° ​​рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `unpublish_draft`: - ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Π°Ρ Ρ€Π°Π±ΠΎΡ‚Π° с ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π°ΠΌΠΈ draft ΠΈ связанного shout - БнятиС shout с ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΏΠΎ ID Ρ‡Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊΠ° - ОбновлСниС кэша послС снятия с ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ - Ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `get_shouts_with_links`: - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° коррСктная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠΎΠ»Π΅ΠΉ `updated_by` ΠΈ `deleted_by`, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ null - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ошибка "Cannot return null for non-nullable field Author.id" - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° сущСствования Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² для ΠΏΠΎΠ»Π΅ΠΉ `updated_by` ΠΈ `deleted_by` - Ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `get_reactions_with_stat`: - Π”ΠΎΠ±Π°Π²Π»Π΅Π½ Π²Ρ‹Π·ΠΎΠ² ΠΌΠ΅Ρ‚ΠΎΠ΄Π° `distinct()` ΠΏΠ΅Ρ€Π΅Π΄ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ `limit` ΠΈ `offset` для прСдотвращСния дублирования Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° докумСнтация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с описаниСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² запроса - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π° сортировка ΠΈ Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с joined eager loads ### Π£Π»ΡƒΡ‡ΡˆΠ΅Π½ΠΎ - БистСма ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ подписок: - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° автоматичСская инвалидация кэша послС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ follow/unfollow - Π£Π½ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок Π² мутациях подписок - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ тСстовыС скрипты `test_unfollow_fix.py` ΠΈ `test_follow_fix.py` для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ исправлСний - ΠžΠ±Π΅ΡΠΏΠ΅Ρ‡Π΅Π½Π° ΠΊΠΎΠ½ΡΠΈΡΡ‚Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ ΠΌΠ΅ΠΆΠ΄Ρƒ опСрациями follow/unfollow - ДокумСнтация систСмы подписок: - ОбновлСн `docs/follower.md` с ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹ΠΌ описаниСм исправлСний Π² follow/unfollow - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΊΠΎΠ΄Π° ΠΈ Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… - Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ всС кСйсы ошибок ΠΈ ΠΈΡ… ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° - **ΠΠžΠ’ΠžΠ•**: ΠœΡƒΡ‚Π°Ρ†ΠΈΡ `getSession` Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ email ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ: - Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ `access=True` ΠΏΡ€ΠΈ сСриализации Π΄Π°Π½Π½Ρ‹Ρ… Π°Π²Ρ‚ΠΎΡ€Π° для Π²Π»Π°Π΄Π΅Π»ΡŒΡ†Π° Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π° - ΠžΠ±Π΅ΡΠΏΠ΅Ρ‡Π΅Π½ доступ ΠΊ Π·Π°Ρ‰ΠΈΡ‰Π΅Π½Π½Ρ‹ΠΌ полям для самого ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΏΠ΅Ρ€ΡΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… #### [0.4.23] - 2025-05-25 ### Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ - Ошибка Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `get_reactions_with_stat`: - Π”ΠΎΠ±Π°Π²Π»Π΅Π½ Π²Ρ‹Π·ΠΎΠ² ΠΌΠ΅Ρ‚ΠΎΠ΄Π° `distinct()` ΠΏΠ΅Ρ€Π΅Π΄ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ `limit` ΠΈ `offset` для прСдотвращСния дублирования Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° докумСнтация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с описаниСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² запроса - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π° сортировка ΠΈ Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с joined eager loads #### [0.4.22] - 2025-05-21 ### Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ - ПанСль управлСния: - Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ окруТСния с Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ ΠΏΠΎ катСгориям - Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ (Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°, ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Ρ€ΠΎΠ»Π΅ΠΉ, ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π·Π²ΡƒΠΊΠ°) - ΠŸΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡ ΠΈ поиск ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΏΠΎ email, ΠΈΠΌΠ΅Π½ΠΈ ΠΈ ID - Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ GraphQL схСмы для Π°Π΄ΠΌΠΈΠ½ΠΊΠΈ: - Π’ΠΈΠΏΡ‹ `AdminUserInfo`, `AdminUserUpdateInput`, `AuthResult`, `Permission`, `SessionInfo` - ΠœΡƒΡ‚Π°Ρ†ΠΈΠΈ для управлСния ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ ΠΈ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ сСрвСрной части: - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° HTTPS Ρ‡Π΅Ρ€Π΅Π· `Granian` с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ `mkcert` - ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ запуска `--https`, `--workers`, `--domain` - БистСма Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ: - Π›ΠΎΠΊΠ°Π»ΡŒΠ½Π°Ρ систСма Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ с сСссиями Π² `Redis` - БистСма Ρ€ΠΎΠ»Π΅ΠΉ ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ (RBAC) - Π—Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ брутфорс Π°Ρ‚Π°ΠΊ - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° `httpOnly` cookies для Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - ΠœΡƒΠ»ΡŒΡ‚ΠΈΡΠ·Ρ‹Ρ‡Π½Ρ‹Π΅ email увСдомлСния ### ИзмСнСно - Π£ΠΏΡ€ΠΎΡ‰Π΅Π½Π° структура клиСнтской части прилоТСния: - ΠœΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΡΡ‚ΠΈΡ‡Π½Π°Ρ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° с основными ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ (авторизация ΠΈ Π°Π΄ΠΌΠΈΠ½ΠΊΠ°) - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΈ ΡƒΠ½ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, слСдуя ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ DRY - Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° систСма ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ с Π·Π°Ρ‰ΠΈΡ‰Π΅Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°ΠΌΠΈ - Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ отвСтствСнности ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ - Π’ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ интСрфСйсы для всСх ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ - ΠžΡ‚ΠΊΠ°Π· ΠΎΡ‚ ТСстких Ρ€Π΅Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΠ² Π² ΠΏΠΎΠ»ΡŒΠ·Ρƒ SolidJS Router - ΠŸΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚Π°Π½ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ: - Унификация Ρ‚ΠΈΠΏΠΎΠ² для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ - ИспользованиС Π΅Π΄ΠΈΠ½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Author Π²ΠΎ всСх запросах - Π Π°ΡΡˆΠΈΡ€Π΅Π½Π½ΠΎΠ΅ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - Унифицированная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСссий ### Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ - ΠšΡ€ΠΈΡ‚ΠΈΡ‡Π΅ΡΠΊΠΈΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с JWT-Ρ‚ΠΎΠΊΠ΅Π½Π°ΠΌΠΈ: - ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Π°Ρ гСнСрация срока истСчСния Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² (exp) - Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π² JWT - ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»Π΅ΠΉ ΠΏΡ€ΠΈ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ - Ошибки Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ: - "Cannot return null for non-nullable field Mutation.login" - "Author password is empty" ΠΏΡ€ΠΈ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ - "Author object has no attribute username" - ΠœΠ΅Ρ‚ΠΎΠ΄ dict() класса Author Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ сСриализуСт Ρ€ΠΎΠ»ΠΈ ΠΊΠ°ΠΊ список словарСй - ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок: - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° валидация email ΠΈ username - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΡΡ‚Π΅ΠΊΡˆΠΈΡ… Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - Π”ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π½Π° NULL ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π² Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€Π°Ρ… - Π’ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹: - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄ dict() класса Author - Π”ΠΎΠ±Π°Π²Π»Π΅Π½ AuthenticationMiddleware - Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ класс AuthenticatedUser ### Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ - ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π°Ρ докумСнтация ΠΏΠΎ систСмС Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² `docs/auth.md` - ОписаниС OAuth ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ - Руководство ΠΏΠΎ RBAC - ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования Π½Π° Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π΅ - Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΠΈ ΠΏΠΎ бСзопасности #### [0.4.21] - 2025-05-10 ### ИзмСнСно - ΠŸΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚Π°Π½Π° пагинация Π² Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ: ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ с ΠΌΠΎΠ΄Π΅Π»ΠΈ page/perPage Π½Π° limit/offset - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с большими списками ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ - ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ GraphQL API для управлСния ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ ### Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ - Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π° ошибка GraphQL "Unknown argument 'page' on field 'Query.adminGetUsers'" - Богласованы ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ ΠΈ сСрвСром #### [0.4.20] - 2025-05-01 ### Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ - ΠŸΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡ списка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π² Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ - БСрвСрная ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΠΈ Π² API для Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ - Поиск ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΏΠΎ email, ΠΈΠΌΠ΅Π½ΠΈ ΠΈ ID ### ИзмСнСно - Π£Π»ΡƒΡ‡ΡˆΠ΅Π½ интСрфСйс Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ - ΠŸΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚Π°Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° GraphQL запросов для списка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ### Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ - ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² - ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок Π² API модулях #### [0.4.19] - 2025-04-14 - dropped `Shout.description` and `Draft.description` to be UX-generated - use redis to init views counters after migrator #### [0.4.18] - 2025-04-10 - Fixed `Topic.stat.authors` and `Topic.stat.comments` - Fixed unique constraint violation for empty slug values: - Modified `update_draft` resolver to handle empty slug values - Modified `create_draft` resolver to prevent empty slug values - Added validation to prevent inserting or updating drafts with empty slug - Fixed database error "duplicate key value violates unique constraint draft_slug_key" #### [0.4.17] - 2025-03-26 - Fixed `'Reaction' object is not subscriptable` error in hierarchical comments: - Modified `get_reactions_with_stat()` to convert Reaction objects to dictionaries - Added default values for limit/offset parameters - Fixed `load_first_replies()` implementation with proper parameter passing - Added doctest with example usage - Limited child comments to 100 per parent for performance #### [0.4.16] - 2025-03-22 - Added hierarchical comments pagination: - Created new GraphQL query `load_comments_branch` for efficient loading of hierarchical comments - Ability to load root comments with their first N replies - Added pagination for both root and child comments - Using existing `comments_count` field in `Stat` type to display number of replies - Added special `first_replies` field to store first replies to a comment - Optimized SQL queries for efficient loading of comment hierarchies - Implemented flexible comment sorting system (by time, rating) #### [0.4.15] - 2025-03-22 - Upgraded caching system described `docs/caching.md` - Module `cache/memorycache.py` removed - Enhanced caching system with backward compatibility: - Unified cache key generation with support for existing naming patterns - Improved Redis operation function with better error handling - Updated precache module to use consistent Redis interface - Integrated revalidator with the invalidation system for better performance - Added comprehensive documentation for the caching system - Enhanced cached_query to support template-based cache keys - Standardized error handling across all cache operations - Optimized cache invalidation system: - Added targeted invalidation for individual entities (authors, topics) - Improved revalidation manager with individual object processing - Implemented batched processing for high-volume invalidations - Reduced Redis operations by using precise key invalidation instead of prefix-based wipes - Added special handling for slug changes in topics - Unified caching system for all models: - Implemented abstract functions `cache_data`, `get_cached_data` and `invalidate_cache_by_prefix` - Added `cached_query` function for unified approach to query caching - Updated resolvers `author.py` and `topic.py` to use the new caching API - Improved logging for cache operations to simplify debugging - Optimized Redis memory usage through key format unification - Improved caching and sorting in Topic and Author modules: - Added support for dictionary sorting parameters in `by` for both modules - Optimized cache key generation for stable behavior with various parameters - Enhanced sorting logic with direction support and arbitrary fields - Added `by` parameter support in the API for getting topics by community - Performance optimizations for author-related queries: - Added SQLAlchemy-managed indexes to `Author`, `AuthorFollower`, `AuthorRating` and `AuthorBookmark` models - Implemented persistent Redis caching for author queries without TTL (invalidated only on changes) - Optimized author retrieval with separate endpoints: - `get_authors_all` - returns all non-deleted authors without statistics - `load_authors_by` - optimized to use caching and efficient sorting and pagination - Improved SQL queries with optimized JOIN conditions and efficient filtering - Added pre-aggregation of statistics (shouts count, followers count) in single efficient queries - Implemented robust cache invalidation on author updates - Created necessary indexes for author lookups by user ID, slug, and timestamps #### [0.4.14] - 2025-03-21 - Significant performance improvements for topic queries: - Added database indexes to optimize JOIN operations - Implemented persistent Redis caching for topic queries (no TTL, invalidated only on changes) - Optimized topic retrieval with separate endpoints for different use cases: - `get_topics_all` - returns all topics without statistics for lightweight listing - `get_topics_by_community` - adds pagination and optimized filtering by community - Added SQLAlchemy-managed indexes directly in ORM models for automatic schema maintenance - Created `sync_indexes()` function for automatic index synchronization during app startup - Reduced database load by pre-aggregating statistics in optimized SQL queries - Added robust cache invalidation on topic create/update/delete operations - Improved query optimization with proper JOIN conditions and specific partial indexes #### [0.4.13] - 2025-03-20 - Fixed Topic objects serialization error in cache/memorycache.py - Improved CustomJSONEncoder to support SQLAlchemy models with dict() method - Enhanced error handling in cache_on_arguments decorator - Modified `load_reactions_by` to include deleted reactions when `include_deleted=true` for proper comment tree building - Fixed featured/unfeatured logic in reaction processing: - Dislike reactions now properly take precedence over likes - Featured status now requires more than 4 likes from users with featured articles - Removed unnecessary filters for deleted reactions since rating reactions are physically deleted - Author's featured status now based on having non-deleted articles with featured_at #### [0.4.12] - 2025-03-19 - `delete_reaction` detects comments and uses `deleted_at` update - `check_to_unfeature` etc. update - dogpile dep in `services/memorycache.py` optimized #### [0.4.11] - 2025-02-12 - `create_draft` resolver requires draft_id fixed - `create_draft` resolver defaults body and title fields to empty string #### [0.4.9] - 2025-02-09 - `Shout.draft` field added - `Draft` entity added - `create_draft`, `update_draft`, `delete_draft` mutations and resolvers added - `create_shout`, `update_shout`, `delete_shout` mutations removed from GraphQL API - `load_drafts` resolver implemented - `publish_` and `unpublish_` mutations and resolvers added - `create_`, `update_`, `delete_` mutations and resolvers added for `Draft` entity - tests with pytest for original auth, shouts, drafts - `Dockerfile` and `pyproject.toml` removed for the simplicity: `Procfile` and `requirements.txt` #### [0.4.8] - 2025-02-03 - `Reaction.deleted_at` filter on `update_reaction` resolver added - `triggers` module updated with `after_shout_handler`, `after_reaction_handler` for cache revalidation - `after_shout_handler`, `after_reaction_handler` now also handle `deleted_at` field - `get_cached_topic_followers` fixed - `get_my_rates_comments` fixed #### [0.4.7] - `get_my_rates_shouts` resolver added with: - `shout_id` and `my_rate` fields in response - filters by `Reaction.deleted_at.is_(None)` - filters by `Reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value])` - filters by `Reaction.reply_to.is_(None)` - uses `local_session()` context manager - returns empty list on errors - SQLAlchemy syntax updated: - `select()` statement fixed for newer versions - `Reaction` model direct selection instead of labeled columns - proper row access with `row[0].shout` and `row[0].kind` - GraphQL resolver fixes: - added root parameter `_` to match schema - proper async/await handling with `@login_required` - error logging added via `logger.error()` #### [0.4.6] - login_accepted decorator added - `docs` added - optimized and unified `load_shouts_*` resolvers with `LoadShoutsOptions` - `load_shouts_bookmarked` resolver fixed - resolvers updates: - new resolvers group `feed` - `load_shouts_authored_by` resolver added - `load_shouts_with_topic` resolver added - `load_shouts_followed` removed - `load_shouts_random_topic` removed - `get_topics_random` removed - model updates: - `ShoutsOrderBy` enum added - `Shout.main_topic` from `ShoutTopic.main` as `Topic` type output - `Shout.created_by` as `Author` type output #### [0.4.5] - `bookmark_shout` mutation resolver added - `load_shouts_bookmarked` resolver added - `get_communities_by_author` resolver added - `get_communities_all` resolver fixed - `Community` stats in orm - `Community` CUDL resolvers added - `Reaction` filter by `Reaction.kind`s - `ReactionSort` enum added - `CommunityFollowerRole` enum added - `InviteStatus` enum added - `Topic.parents` ids added - `get_shout` resolver accepts slug or shout_id #### [0.4.4] - `followers_stat` removed for shout - sqlite3 support added - `rating_stat` and `commented_stat` fixes #### [0.4.3] - cache reimplemented - load shouts queries unified - `followers_stat` removed from shout #### [0.4.2] - reactions load resolvers separated for ratings (no stats) and comments - reactions stats improved - `load_comment_ratings` separate resolver #### [0.4.1] - follow/unfollow logic updated and unified with cache #### [0.4.0] - chore: version migrator synced - feat: precache_data on start - fix: store id list for following cache data - fix: shouts stat filter out deleted #### [0.3.5] - cache isolated to services - topics followers and authors cached - redis stores lists of ids #### [0.3.4] - `load_authors_by` from cache #### [0.3.3] - feat: sentry integration enabled with glitchtip - fix: reindex on update shout - packages upgrade, isort - separated stats queries for author and topic - fix: feed featured filter - fts search removed #### [0.3.2] - redis cache for what author follows - redis cache for followers - graphql add query: get topic followers #### [0.3.1] - enabling sentry - long query log report added - editor fixes - authors links cannot be updated by `update_shout` anymore #### [0.3.0] - `Shout.featured_at` timestamp of the frontpage featuring event - added proposal accepting logics - schema modulized - Shout.visibility removed #### [0.2.22] - added precommit hook - fmt - granian asgi #### [0.2.21] - fix: rating logix - fix: `load_top_random_shouts` - resolvers: `add_stat_*` refactored - services: use google analytics - services: minor fixes search #### [0.2.20] - services: ackee removed - services: following manager fixed - services: import views.json #### [0.2.19] - fix: adding `author` role - fix: stripping `user_id` in auth connector #### [0.2.18] - schema: added `Shout.seo` string field - resolvers: added `/new-author` webhook resolver - resolvers: added reader.load_shouts_top_random - resolvers: added reader.load_shouts_unrated - resolvers: community follower id property name is `.author` - resolvers: `get_authors_all` and `load_authors_by` - services: auth connector upgraded #### [0.2.17] - schema: enum types workaround, `ReactionKind`, `InviteStatus`, `ShoutVisibility` - schema: `Shout.created_by`, `Shout.updated_by` - schema: `Shout.authors` can be empty - resolvers: optimized `reacted_shouts_updates` query #### [0.2.16] - resolvers: collab inviting logics - resolvers: queries and mutations revision and renaming - resolvers: `delete_topic(slug)` implemented - resolvers: added `get_shout_followers` - resolvers: `load_shouts_by` filters implemented - orm: invite entity - schema: `Reaction.range` -> `Reaction.quote` - filters: `time_ago` -> `after` - httpx -> aiohttp #### [0.2.15] - schema: `Shout.created_by` removed - schema: `Shout.mainTopic` removed - services: cached elasticsearch connector - services: auth is using `user_id` from authorizer - resolvers: `notify_*` usage fixes - resolvers: `getAuthor` now accepts slug, `user_id` or `author_id` - resolvers: login_required usage fixes #### [0.2.14] - schema: some fixes from migrator - schema: `.days` -> `.time_ago` - schema: `excludeLayout` + `layout` in filters -> `layouts` - services: db access simpler, no contextmanager - services: removed Base.create() method - services: rediscache updated - resolvers: get_reacted_shouts_updates as followedReactions query #### [0.2.13] - services: db context manager - services: `ViewedStorage` fixes - services: views are not stored in core db anymore - schema: snake case in model fields names - schema: no DateTime scalar - resolvers: `get_my_feed` comments filter reactions body.is_not('') - resolvers: `get_my_feed` query fix - resolvers: `LoadReactionsBy.days` -> `LoadReactionsBy.time_ago` - resolvers: `LoadShoutsBy.days` -> `LoadShoutsBy.time_ago` #### [0.2.12] - `Author.userpic` -> `Author.pic` - `CommunityFollower.role` is string now - `Author.user` is string now #### [0.2.11] - redis interface updated - `viewed` interface updated - `presence` interface updated - notify on create, update, delete for reaction and shout - notify on follow / unfollow author - use pyproject - devmode fixed #### [0.2.10] - community resolvers connected #### [0.2.9] - starlette is back, aiohttp removed - aioredis replaced with aredis #### [0.2.8] - refactored #### [0.2.7] - `loadFollowedReactions` now with `login_required` - notifier service api draft - added `shout` visibility kind in schema - community isolated from author in orm #### [0.2.6] - redis connection pool - auth context fixes - communities orm, resolvers, schema #### [0.2.5] - restructured - all users have their profiles as authors in core - `gittask`, `inbox` and `auth` logics removed - `settings` moved to base and now smaller - new outside auth schema - removed `gittask`, `auth`, `inbox`, `migration`