From a58d6f31fa211d2df5f6bb7973a0120ac8b8b905 Mon Sep 17 00:00:00 2001 From: Martin Porwoll Date: Sun, 1 Mar 2026 09:19:31 +0000 Subject: [PATCH] feat: add auth middleware and bot setup with session and rate limiting Co-Authored-By: Claude Opus 4.6 --- src/bot.ts | 57 ++++++++++++++++++++++++++++++++++++++++++ src/middleware/auth.ts | 17 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/bot.ts create mode 100644 src/middleware/auth.ts diff --git a/src/bot.ts b/src/bot.ts new file mode 100644 index 0000000..4230b6b --- /dev/null +++ b/src/bot.ts @@ -0,0 +1,57 @@ +import { Bot, session, type Context, type SessionFlavor } from 'grammy'; +import { config } from './config.js'; +import { authMiddleware } from './middleware/auth.js'; +import { createLogger } from './utils/logger.js'; + +const log = createLogger('Bot'); + +interface SessionData { + selectedTenantId: number; + selectedTenantName: string; +} + +type BotContext = Context & SessionFlavor; + +// Rate limiting: track uploads per user +const uploadCounts = new Map(); + +function checkRateLimit(userId: number): { allowed: boolean; retryAfter?: number } { + const now = Date.now(); + const entry = uploadCounts.get(userId); + + if (!entry || entry.resetAt <= now) { + uploadCounts.set(userId, { count: 1, resetAt: now + 60_000 }); + return { allowed: true }; + } + + if (entry.count >= 10) { + const retryAfter = Math.ceil((entry.resetAt - now) / 1000); + return { allowed: false, retryAfter }; + } + + entry.count++; + return { allowed: true }; +} + +function createBot(): Bot { + const bot = new Bot(config.telegram.botToken); + + // Session middleware + bot.use( + session({ + initial: (): SessionData => ({ + selectedTenantId: config.defaultTenantId, + selectedTenantName: 'Default', + }), + }), + ); + + // Auth middleware + bot.use(authMiddleware); + + log.info('Bot instance created'); + return bot; +} + +export { createBot, checkRateLimit }; +export type { BotContext, SessionData }; diff --git a/src/middleware/auth.ts b/src/middleware/auth.ts new file mode 100644 index 0000000..d91d3ab --- /dev/null +++ b/src/middleware/auth.ts @@ -0,0 +1,17 @@ +import { type Context, type NextFunction } from 'grammy'; +import { config } from '../config.js'; +import { createLogger } from '../utils/logger.js'; + +const log = createLogger('Auth'); + +export async function authMiddleware(ctx: Context, next: NextFunction): Promise { + const userId = ctx.from?.id; + + if (!userId || !config.telegram.allowedUserIds.includes(userId)) { + log.warn(`Unauthorized access attempt from user ${userId || 'unknown'}`); + await ctx.reply('⛔ Du bist nicht autorisiert, diesen Bot zu verwenden.'); + return; + } + + await next(); +}