package http import ( "net/http" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/hook" ) // RefreshPath — адрес хранилища, которым сессия продлевает саму себя. const RefreshPath = "/api/collections/users/auth-refresh" // BlockSessionRefresh закрывает продление сессии. // // Хранилище выдаёт сессию продлеваемой: предъявитель значения меняет его на // новое, с новым сроком, и делает это сколько угодно раз, никуда не входя. При // живом продлении срок жизни сессии перестаёт что-либо значить, а вместе с ним // перестаёт работать единственный канал, которым отзыв доступа у провайдера // доходит до сервиса, — сервис после входа к провайдеру не обращается. // // Решение владельца от 2026-08-12: продление выключено, цена — вход раз в // семь суток. func BlockSessionRefresh() *hook.Handler[*core.RequestEvent] { return &hook.Handler[*core.RequestEvent]{ Id: "transcriberBlockSessionRefresh", Priority: apis.DefaultLoadAuthTokenMiddlewarePriority - 2, Func: func(e *core.RequestEvent) error { if e.Request.URL.Path == RefreshPath { return e.JSON(http.StatusNotFound, map[string]string{ "error": "Продление сессии выключено", }) } return e.Next() }, } } // SessionFromCookie перекладывает значение куки сессии в заголовок, которым // хранилище читает предъявленную сессию. // // Куки хранилище не читает вовсе — только заголовок `Authorization`. Браузер же // сам заголовка не шлёт, а своей страницы со скриптом у сервиса нет, поэтому // сессия предъявляется кукой, а способ проверки остаётся один. // // Предъявленный заголовок побеждает: иначе браузер с сессионной кукой получал // бы на собственных адресах хранилища не то, что предъявил. // // Слой стоит раньше проверки токена: тот идёт с приоритетом // DefaultLoadAuthTokenMiddlewarePriority и к этому моменту заголовок должен // быть на месте. func SessionFromCookie() *hook.Handler[*core.RequestEvent] { return &hook.Handler[*core.RequestEvent]{ Id: "transcriberSessionFromCookie", Priority: apis.DefaultLoadAuthTokenMiddlewarePriority - 1, Func: func(e *core.RequestEvent) error { if e.Request.Header.Get("Authorization") != "" { return e.Next() } cookie, err := e.Request.Cookie(SessionCookieName) if err != nil || cookie.Value == "" { return e.Next() } e.Request.Header.Set("Authorization", cookie.Value) return e.Next() }, } }