fix(invites): картинки оформления отдаются без сессии для страницы приглашения

- GET /files/{id} без сессии отдаёт только оформление сервера и картинку
  приглашения (guild_icon, guild_banner, guild_splash, invite_background):
  их показывают до входа (AGENT.md 7.9), остальное по-прежнему требует сессии
- optionalUser резолвит сессию без ответа об ошибке; путь файла проверяется на
  принадлежность каталогу данных (AGENT.md 9.2)
- аватар пригласившего показывается только вошедшим
- тесты: Go (splash анонимно, вложение закрыто) и правки живого скрипта
This commit is contained in:
2026-09-21 19:30:25 +03:00
parent 566e1cf981
commit 72537e9ff9
4 changed files with 185 additions and 17 deletions
+18 -7
View File
@@ -187,18 +187,29 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
}
// authenticate читает сессию из cookie или Bearer-токена (desktop, AGENT.md 8.1).
// optionalUser резолвит сессию, не отвечая ошибкой: `nil` — анонимный запрос.
// Нужен ручкам, которые часть данных отдают и без входа (страница приглашения).
func (s *Server) optionalUser(ctx context.Context, r *http.Request) (*store.User, error) {
if s.auth == nil {
return nil, nil
}
token := sessionToken(r)
if token == "" {
return nil, nil
}
user, _, err := s.auth.ResolveSession(ctx, token)
if err != nil {
return nil, err
}
return user, nil
}
func (s *Server) authenticate(w http.ResponseWriter, r *http.Request) (*store.User, *store.Session, bool) {
if s.auth == nil {
writeAPIError(w, auth.ErrSessionExpired)
return nil, nil, false
}
token := ""
if cookie, err := r.Cookie(sessionCookieName); err == nil {
token = cookie.Value
}
if token == "" {
token = normalizeBearer(r.Header.Get("Authorization"))
}
token := sessionToken(r)
if token == "" {
writeAPIError(w, auth.ErrSessionExpired)
return nil, nil, false