fix(customer): restore storefront login and session auth - #321
Conversation
|
Вань, серьезные изменения. А ты это проверял руками? Или как всегда только теоритическая автоматизированная проверка? |
Привет! Давай пока не вливать, дополнительно все протестирую |
5c0654f to
fa8e4f9
Compare
|
@biz87, учёл твой комментарий: в описание PR добавил обязательный ручной чеклист перед merge (logout через сайдбар, пароль из менеджера, reload ЛК, token/get после login). В этой итерации дополнительно:
Автоматически прогнал |
76722f6 to
275c365
Compare
biz87
left a comment
There was a problem hiding this comment.
🛑 PR не проходит php -l — метод resolveOrCreateToken() в src/Services/TokenService.php оборван.
После шага 2 (проверка cookie) метод не создаёт новый токен и не закрывается }:
if ($resolved['reason'] === 'expired' || $resolved['reason'] === 'missing') {
CookieHelper::clearTokenCookie($this->modx);
}
}
// ← отсутствует шаг 3 (mint нового токена + return) и закрывающая } метода
/**
* Renew expired API token TTL and hydrate $_SESSION from DB row.
*/
public function syncSessionFromToken(msCustomerToken $tokenObj): voidИз-за этого парсер видит public function syncSessionFromToken внутри незакрытого тела метода → syntax error, unexpected token "public" на TokenService.php:233, и весь файл перестаёт компилироваться (каскад ~17 ошибок PHPStan до EOF).
Докблок самого метода (стр. ~181) обещает: «Expired cookie tokens are discarded (not auto-renewed) and a new token is created» — но ветка создания нового токена в теле отсутствует.
Проверка на текущем HEAD (275c365):
$ php -l src/Services/TokenService.php
PHP Parse error: syntax error, unexpected token "public" ... on line 233
Похоже, в PR попал коммит, отличный от того, на котором прогонялся composer ci:php (в описании указан exit 0) — на текущем HEAD он бы упал.
Просьба: дописать шаг 3 (mint нового токена + return) и закрыть метод }, затем прогнать php -l / composer ci:php и вернуть на ревью. До этого фикса придержим и остальной auth-кластер (#435, #441, #462, #351, #440), т.к. они ложатся на восстановленный этим PR флоу.
275c365 to
49a695f
Compare
Restore step 3 (generateCustomerToken + return) and close the method so TokenService.php parses again; addresses PR #321 review.
Unify token/session binding after login and registration, restore SSR auth from cookie without minting guest tokens, and align email/password handling between manager and storefront.
Prevent guest token mint and middleware from wiping an authenticated customer session, fail register auto-login when session bind fails, and add focused regression tests for email normalize and API payload shape.
Snippet and API logout now revoke tokens, mint a guest cookie, and extend TTL in DB on refresh. Registration keeps the account if auto-login session bind fails and points the user to the login page.
Fail register auto-login when session bind fails, clear customer_id on guest token hydrate, enforce active/blocked checks in TokenMiddleware, and harden save/TTL/session observability around auth flows.
Route login/logout/guest mint through TokenService::persistApiToken so session/cookie hydrate from one DB row, move normalizeEmail to AuthManager, and drop the misplaced PHP ApiClient payload test.
Return distinct blocked/inactive login messages without lockout increment, add legacy email lookup with soft normalize on success, drop dead remember checkbox, and add smoke tests for guest wipe and token reuse guards.
Mint a fresh token on establishCustomerSession, transfer guest/own draft cart then revoke the old token, require session token ownership in middleware/checkAuth, and clear local session after password reset revoke.
Pass raw email into authenticate/register for legacy case lookup, always revoke the previous browser token after login rotation, enforce token expiry in session ownership checks, and harden logout/clearAuthSession.
Expose POST /api/v1/customer/logout so AuthUI and API clients can revoke the session token after login; closes the 404 gap found during #285 QA.
Restore step 3 (generateCustomerToken + return) and close the method so TokenService.php parses again; addresses PR #321 review.
49a695f to
676b294
Compare
Add getBindableTokenString/restoreSessionFromCookie/ensureSessionActive, define $customerId in TokenMiddleware, and simplify SessionHelper start.
|
@biz87 по ревью #4801368948: оборванный Можно пересмотреть с актуального tip ветки |
# Conflicts: # core/components/minishop3/src/Controllers/Api/Manager/CustomersController.php
…ogout (#462) TokenMiddleware authorized non-public requests from $_SESSION['ms3']['customer_id'] alone, without re-validating an API token against the DB — so after a revoke on one device, another device with a live PHP session kept access (#409). - TokenMiddleware: the session short-circuit (isCustomerSessionAllowed) is gone; the session customer_token cache is treated as a token candidate and must pass resolveApiToken (DB validation). A stale customer_id with no resolvable token is cleared and falls through to 401. - AuthorizedCustomerTrait (used by CustomerAddress/CustomerOrder controllers): resolves the customer from a validated token only, no session-customer_id fallback. - Logout processor: regenerates the session id and resolves the customer from the validated token when the PHP session is empty. - Adds TokenSessionRevokePolicyTest guarding all of the above. Rebased on #321. Closes #409.
Описание
Починена авторизация покупателя на витрине и в ЛК (#285): после входа сессия не держалась, редирект возвращал на login, повторный вход падал, пароль из менеджера не сходился с проверкой на витрине.
Корневые причины
AuthUIчиталresult.object, Web API отдаёт payload вdatatoken/get/ middleware могли затереть auth guest-токеном?action=logoutчистил только PHP-сессию и оставлял auth cookie (сrestoreSessionFromCookieэто снова логинило)POST /api/v1/customer/logout(API logout → 404)Backend
AuthManager::establishCustomerSession()— bind customer ↔ token ↔ cookie ↔ session ↔ draft; ротация токена на loginAuthManager::logoutCurrentCustomer()— общий logout для API и snippetTokenService::restoreSessionFromCookie()+ restore-before-mint; guest token не затирает authcustomer_idTokenService::persistApiToken()/sessionTokenBelongsToCustomer()— единый mint/hydrate pathPasswordAuthProvider::normalizeEmail()/hashPassword(); manager update через тот же pathSessionHelper::ensureActive();session_regenerate_id(true)после loginweb.php:POST /api/v1/customer/logout→Logoutprocessor (+tokenMiddleware)Frontend
ApiClient.getPayload()—dataс fallback наobjectAuthUIберёт redirect изgetPayloadТесты
CustomerAuthNormalizeEmailTest.phpCustomerAuthSessionSemanticsTest.php(policy smoke, не full MODX E2E)Тип изменений
Связанные Issues
Closes #285
Как это было протестировано?
https://project.test, 2026-07-16)Конфигурация:
fix/285-customer-auth(tip152fdc4+ локальноweb.phplogout route)project.test#2051(ms3-customer-auth-test.html,[[!msCustomer]])#433(http-order1779591899@test.local)Gate (exit 0):
php -lна затронутых PHPphp core/components/minishop3/tests/CustomerAuthNormalizeEmailTest.phpphp core/components/minishop3/tests/CustomerAuthSessionSemanticsTest.phpРучной чеклист — результаты
MgrPass285!→ вход на витрине#2051, профиль?action=logout) → снова открыть ЛКPOST /customer/logoutПримечания по стенду
ms3_customer_redirect_after_login = 2051msCustomerсинхронизированы с файлами в БД MODXweb.phpпроверен на live; в ветке пока uncommitted — нужен отдельный commit перед mergeСкриншоты (если применимо)
Чеклист
Дополнительные заметки
bindDraftToCustomer().ms3_customer_register_success_login_requiredи redirect на login (не «email занят» при повторе).TokenService/ snippet secrets; email-verification path с legacymsCustomer.token.logoutCurrentCustomer().