feat: make tenant selection mandatory - no default tenant, user must choose via /tenant

This commit is contained in:
Martin Porwoll 2026-03-01 09:37:11 +00:00
parent 22e9a59e2e
commit 132acf0ae7
3 changed files with 37 additions and 8 deletions

View file

@ -6,7 +6,7 @@ import { createLogger } from './utils/logger.js';
const log = createLogger('Bot'); const log = createLogger('Bot');
interface SessionData { interface SessionData {
selectedTenantId: number; selectedTenantId: number | null;
selectedTenantName: string; selectedTenantName: string;
} }
@ -41,7 +41,7 @@ function createBot(): Bot<BotContext> {
session({ session({
initial: (): SessionData => ({ initial: (): SessionData => ({
selectedTenantId: config.defaultTenantId, selectedTenantId: config.defaultTenantId,
selectedTenantName: 'Default', selectedTenantName: config.defaultTenantId ? 'Default' : '',
}), }),
}), }),
); );

View file

@ -10,7 +10,7 @@ interface Config {
email: string; email: string;
password: string; password: string;
}; };
defaultTenantId: number; defaultTenantId: number | null;
logLevel: string; logLevel: string;
nodeEnv: string; nodeEnv: string;
} }
@ -43,7 +43,7 @@ export const config: Config = {
email: requireEnv('PAYLOAD_ADMIN_EMAIL'), email: requireEnv('PAYLOAD_ADMIN_EMAIL'),
password: requireEnv('PAYLOAD_ADMIN_PASSWORD'), password: requireEnv('PAYLOAD_ADMIN_PASSWORD'),
}, },
defaultTenantId: Number(process.env.DEFAULT_TENANT_ID || '4'), defaultTenantId: process.env.DEFAULT_TENANT_ID ? Number(process.env.DEFAULT_TENANT_ID) : null,
logLevel: process.env.LOG_LEVEL || 'info', logLevel: process.env.LOG_LEVEL || 'info',
nodeEnv: process.env.NODE_ENV || 'development', nodeEnv: process.env.NODE_ENV || 'development',
}; };

View file

@ -72,6 +72,10 @@ async function downloadTelegramFile(
return { buffer, mimeType, filePath }; return { buffer, mimeType, filePath };
} }
function requireTenant(ctx: BotContext): ctx is BotContext & { session: { selectedTenantId: number } } {
return ctx.session.selectedTenantId !== null;
}
async function processUpload( async function processUpload(
ctx: BotContext, ctx: BotContext,
fileId: string, fileId: string,
@ -81,6 +85,15 @@ async function processUpload(
const userId = ctx.from?.id; const userId = ctx.from?.id;
if (!userId) return; if (!userId) return;
if (!requireTenant(ctx)) {
await ctx.api.editMessageText(
ctx.chat!.id,
statusMessageId,
'⚠️ Bitte wähle zuerst einen Tenant mit /tenant',
);
return;
}
// Rate limit check // Rate limit check
const rateCheck = checkRateLimit(userId); const rateCheck = checkRateLimit(userId);
if (!rateCheck.allowed) { if (!rateCheck.allowed) {
@ -129,6 +142,11 @@ async function processAlbum(
ctx: BotContext, ctx: BotContext,
messages: Array<{ fileId: string; filename: string; mimeType: string }>, messages: Array<{ fileId: string; filename: string; mimeType: string }>,
): Promise<void> { ): Promise<void> {
if (!requireTenant(ctx)) {
await ctx.reply('⚠️ Bitte wähle zuerst einen Tenant mit /tenant');
return;
}
const total = Math.min(messages.length, 10); const total = Math.min(messages.length, 10);
const statusMsg = await ctx.reply(`\u23f3 Album wird hochgeladen (0/${total})...`); const statusMsg = await ctx.reply(`\u23f3 Album wird hochgeladen (0/${total})...`);
let successCount = 0; let successCount = 0;
@ -187,12 +205,18 @@ async function processAlbum(
export function registerHandlers(bot: Bot<BotContext>): void { export function registerHandlers(bot: Bot<BotContext>): void {
// /start command // /start command
bot.command('start', async (ctx) => { bot.command('start', async (ctx) => {
let tenantLine: string;
if (ctx.session.selectedTenantId !== null) {
const tenantName = await getTenantName(ctx.session.selectedTenantId); const tenantName = await getTenantName(ctx.session.selectedTenantId);
ctx.session.selectedTenantName = tenantName; ctx.session.selectedTenantName = tenantName;
tenantLine = `Aktueller Tenant: *${escapeMarkdown(tenantName)}*`;
} else {
tenantLine = `⚠️ *Kein Tenant gewählt* \\- nutze /tenant`;
}
const text = const text =
`\ud83d\udcf7 *Payload Media Bot*\n\n` + `\ud83d\udcf7 *Payload Media Bot*\n\n` +
`Willkommen\\! Aktueller Tenant: *${escapeMarkdown(tenantName)}*\n\n` + `Willkommen\\! ${tenantLine}\n\n` +
`*Befehle:*\n` + `*Befehle:*\n` +
`/tenant \\- Tenant wechseln\n` + `/tenant \\- Tenant wechseln\n` +
`/list \\- Letzte 5 Medien anzeigen\n` + `/list \\- Letzte 5 Medien anzeigen\n` +
@ -216,6 +240,11 @@ export function registerHandlers(bot: Bot<BotContext>): void {
// /list command — show last 5 media items // /list command — show last 5 media items
bot.command('list', async (ctx) => { bot.command('list', async (ctx) => {
if (!requireTenant(ctx)) {
await ctx.reply('⚠️ Bitte wähle zuerst einen Tenant mit /tenant');
return;
}
try { try {
const result = await payloadClient.listMedia(ctx.session.selectedTenantId, 5); const result = await payloadClient.listMedia(ctx.session.selectedTenantId, 5);
@ -254,7 +283,7 @@ export function registerHandlers(bot: Bot<BotContext>): void {
`\ud83d\udcca *Bot Status*\n\n` + `\ud83d\udcca *Bot Status*\n\n` +
`\u23f1 Uptime: ${escapeMarkdown(formatUptime())}\n` + `\u23f1 Uptime: ${escapeMarkdown(formatUptime())}\n` +
`\ud83d\udfe2 API: ${healthy ? 'Erreichbar' : 'Nicht erreichbar'}\n` + `\ud83d\udfe2 API: ${healthy ? 'Erreichbar' : 'Nicht erreichbar'}\n` +
`\ud83c\udfe2 Tenant: ${escapeMarkdown(ctx.session.selectedTenantName)} \\(ID ${ctx.session.selectedTenantId}\\)\n` + `\ud83c\udfe2 Tenant: ${ctx.session.selectedTenantId !== null ? `${escapeMarkdown(ctx.session.selectedTenantName)} \\(ID ${ctx.session.selectedTenantId}\\)` : 'Nicht gewählt'}\n` +
`\ud83d\udd11 Token läuft ab: ${escapeMarkdown(expiryStr)}`; `\ud83d\udd11 Token läuft ab: ${escapeMarkdown(expiryStr)}`;
await ctx.reply(text, { parse_mode: 'MarkdownV2' }); await ctx.reply(text, { parse_mode: 'MarkdownV2' });