Files
telegram-gateway/telegram_types.go
Gabriel Radureau 07115e3162
Some checks failed
Docker Build / build-and-push-image (push) Failing after 18s
Phase 1.5 — auth layer (Redis sessions, allowlist, requireAuth)
Adds an authentication layer in front of the bot handlers :

- Auth handler on the principal bot (@arcodange_factory_bot, slug
  factory) parses /start, /auth <code>, /whoami, /logout. On a
  successful /auth, the message containing the code is best-effort
  deleted from the user's chat (replay defense).
- Redis-backed sessions (key tg-gw:auth:<from.id>, TTL 24h, configurable
  via AUTH_SESSION_TTL). Constant-time secret compare via crypto/subtle.
- ALLOWED_USERS env (CSV of Telegram user IDs) — silent-drops anyone
  not in the list before the auth gate runs.
- New per-bot field 'requireAuth' (pointer-bool). Default = true (secure
  by default). Auto-forced to false for handler=auth (chicken-and-egg).
- Server gates: allowlist first, then requireAuth before handler dispatch.
- Fail-at-startup if a bot is configured with handler=auth or
  requireAuth: true while AUTH_SECRET is unset.

Design: factory/docs/adr/20260509-telegram-gateway-auth.md (in factory PR).
User docs: AUTH.md (new), HOWTO_ADD_BOT.md (Cas 2 updated for default
true and gated flow).

New deps: github.com/redis/go-redis/v9.

Refs ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 1.5.
2026-05-09 13:56:30 +02:00

75 lines
2.0 KiB
Go

package main
type Update struct {
UpdateID int64 `json:"update_id"`
Message *Message `json:"message,omitempty"`
EditedMessage *Message `json:"edited_message,omitempty"`
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
}
type Message struct {
MessageID int64 `json:"message_id"`
From *User `json:"from,omitempty"`
Chat Chat `json:"chat"`
Date int64 `json:"date,omitempty"`
Text string `json:"text,omitempty"`
}
type Chat struct {
ID int64 `json:"id"`
Type string `json:"type,omitempty"`
}
type User struct {
ID int64 `json:"id"`
IsBot bool `json:"is_bot,omitempty"`
Username string `json:"username,omitempty"`
FirstName string `json:"first_name,omitempty"`
}
type CallbackQuery struct {
ID string `json:"id"`
From *User `json:"from,omitempty"`
Message *Message `json:"message,omitempty"`
Data string `json:"data,omitempty"`
}
func (u Update) ChatID() (int64, bool) {
switch {
case u.Message != nil:
return u.Message.Chat.ID, true
case u.EditedMessage != nil:
return u.EditedMessage.Chat.ID, true
case u.CallbackQuery != nil && u.CallbackQuery.Message != nil:
return u.CallbackQuery.Message.Chat.ID, true
}
return 0, false
}
// UserID extracts the Telegram user ID (`from.id`) from whichever sub-payload
// is set. Used by the auth layer (factory bot session, requireAuth gate, allowlist).
// See factory/docs/adr/20260509-telegram-gateway-auth.md.
func (u Update) UserID() (int64, bool) {
switch {
case u.Message != nil && u.Message.From != nil:
return u.Message.From.ID, true
case u.EditedMessage != nil && u.EditedMessage.From != nil:
return u.EditedMessage.From.ID, true
case u.CallbackQuery != nil && u.CallbackQuery.From != nil:
return u.CallbackQuery.From.ID, true
}
return 0, false
}
func (u Update) Text() string {
switch {
case u.Message != nil:
return u.Message.Text
case u.EditedMessage != nil:
return u.EditedMessage.Text
case u.CallbackQuery != nil:
return u.CallbackQuery.Data
}
return ""
}