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');
interface SessionData {
selectedTenantId: number;
selectedTenantId: number | null;
selectedTenantName: string;
}
@ -41,7 +41,7 @@ function createBot(): Bot<BotContext> {
session({
initial: (): SessionData => ({
selectedTenantId: config.defaultTenantId,
selectedTenantName: 'Default',
selectedTenantName: config.defaultTenantId ? 'Default' : '',
}),
}),
);

View file

@ -10,7 +10,7 @@ interface Config {
email: string;
password: string;
};
defaultTenantId: number;
defaultTenantId: number | null;
logLevel: string;
nodeEnv: string;
}
@ -43,7 +43,7 @@ export const config: Config = {
email: requireEnv('PAYLOAD_ADMIN_EMAIL'),
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',
nodeEnv: process.env.NODE_ENV || 'development',
};

View file

@ -72,6 +72,10 @@ async function downloadTelegramFile(
return { buffer, mimeType, filePath };
}
function requireTenant(ctx: BotContext): ctx is BotContext & { session: { selectedTenantId: number } } {
return ctx.session.selectedTenantId !== null;
}
async function processUpload(
ctx: BotContext,
fileId: string,
@ -81,6 +85,15 @@ async function processUpload(
const userId = ctx.from?.id;
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
const rateCheck = checkRateLimit(userId);
if (!rateCheck.allowed) {
@ -129,6 +142,11 @@ async function processAlbum(
ctx: BotContext,
messages: Array<{ fileId: string; filename: string; mimeType: string }>,
): 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 statusMsg = await ctx.reply(`\u23f3 Album wird hochgeladen (0/${total})...`);
let successCount = 0;
@ -187,12 +205,18 @@ async function processAlbum(
export function registerHandlers(bot: Bot<BotContext>): void {
// /start command
bot.command('start', async (ctx) => {
let tenantLine: string;
if (ctx.session.selectedTenantId !== null) {
const tenantName = await getTenantName(ctx.session.selectedTenantId);
ctx.session.selectedTenantName = tenantName;
tenantLine = `Aktueller Tenant: *${escapeMarkdown(tenantName)}*`;
} else {
tenantLine = `⚠️ *Kein Tenant gewählt* \\- nutze /tenant`;
}
const text =
`\ud83d\udcf7 *Payload Media Bot*\n\n` +
`Willkommen\\! Aktueller Tenant: *${escapeMarkdown(tenantName)}*\n\n` +
`Willkommen\\! ${tenantLine}\n\n` +
`*Befehle:*\n` +
`/tenant \\- Tenant wechseln\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
bot.command('list', async (ctx) => {
if (!requireTenant(ctx)) {
await ctx.reply('⚠️ Bitte wähle zuerst einen Tenant mit /tenant');
return;
}
try {
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` +
`\u23f1 Uptime: ${escapeMarkdown(formatUptime())}\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)}`;
await ctx.reply(text, { parse_mode: 'MarkdownV2' });