mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 17:34:03 +00:00
feat(db): enforce runtime RLS boundaries
This commit is contained in:
@@ -4,6 +4,8 @@ export interface BotRuntimeConfig {
|
||||
telegramBotToken: string
|
||||
telegramWebhookSecret: string
|
||||
telegramWebhookPath: string
|
||||
appDatabaseUrl?: string
|
||||
workerDatabaseUrl?: string
|
||||
databaseUrl?: string
|
||||
purchaseTopicIngestionEnabled: boolean
|
||||
financeCommandsEnabled: boolean
|
||||
@@ -101,20 +103,22 @@ function parsePositiveInteger(raw: string | undefined, fallback: number, key: st
|
||||
|
||||
export function getBotRuntimeConfig(env: NodeJS.ProcessEnv = process.env): BotRuntimeConfig {
|
||||
const databaseUrl = parseOptionalValue(env.DATABASE_URL)
|
||||
const appDatabaseUrl = parseOptionalValue(env.APP_DATABASE_URL)
|
||||
const workerDatabaseUrl = parseOptionalValue(env.WORKER_DATABASE_URL)
|
||||
const schedulerSharedSecret = parseOptionalValue(env.SCHEDULER_SHARED_SECRET)
|
||||
const schedulerOidcAllowedEmails = parseOptionalCsv(env.SCHEDULER_OIDC_ALLOWED_EMAILS)
|
||||
const miniAppAllowedOrigins = parseOptionalCsv(env.MINI_APP_ALLOWED_ORIGINS)
|
||||
const miniAppUrl = parseOptionalValue(env.MINI_APP_URL)
|
||||
|
||||
const purchaseTopicIngestionEnabled = databaseUrl !== undefined
|
||||
|
||||
const financeCommandsEnabled = databaseUrl !== undefined
|
||||
const anonymousFeedbackEnabled = databaseUrl !== undefined
|
||||
const assistantEnabled = databaseUrl !== undefined
|
||||
const miniAppAuthEnabled = databaseUrl !== undefined
|
||||
const purchaseTopicIngestionEnabled = workerDatabaseUrl !== undefined
|
||||
const financeCommandsEnabled = workerDatabaseUrl !== undefined
|
||||
const anonymousFeedbackEnabled = workerDatabaseUrl !== undefined
|
||||
const assistantEnabled = workerDatabaseUrl !== undefined
|
||||
const miniAppAuthEnabled = appDatabaseUrl !== undefined
|
||||
const hasSchedulerOidcConfig = schedulerOidcAllowedEmails.length > 0
|
||||
const reminderJobsEnabled =
|
||||
databaseUrl !== undefined && (schedulerSharedSecret !== undefined || hasSchedulerOidcConfig)
|
||||
workerDatabaseUrl !== undefined &&
|
||||
(schedulerSharedSecret !== undefined || hasSchedulerOidcConfig)
|
||||
|
||||
const runtime: BotRuntimeConfig = {
|
||||
port: parsePort(env.PORT),
|
||||
@@ -173,6 +177,12 @@ export function getBotRuntimeConfig(env: NodeJS.ProcessEnv = process.env): BotRu
|
||||
if (databaseUrl !== undefined) {
|
||||
runtime.databaseUrl = databaseUrl
|
||||
}
|
||||
if (appDatabaseUrl !== undefined) {
|
||||
runtime.appDatabaseUrl = appDatabaseUrl
|
||||
}
|
||||
if (workerDatabaseUrl !== undefined) {
|
||||
runtime.workerDatabaseUrl = workerDatabaseUrl
|
||||
}
|
||||
if (schedulerSharedSecret !== undefined) {
|
||||
runtime.schedulerSharedSecret = schedulerSharedSecret
|
||||
}
|
||||
|
||||
@@ -47,7 +47,11 @@ import { createReminderJobsHandler } from './reminder-jobs'
|
||||
import { registerReminderTopicUtilities } from './reminder-topic-utilities'
|
||||
import { createSchedulerRequestAuthorizer } from './scheduler-auth'
|
||||
import { createBotWebhookServer } from './server'
|
||||
import { createMiniAppAuthHandler, createMiniAppJoinHandler } from './miniapp-auth'
|
||||
import {
|
||||
createMiniAppAuthHandler,
|
||||
createMiniAppJoinHandler,
|
||||
type MiniAppAuthorizedSession
|
||||
} from './miniapp-auth'
|
||||
import { createMiniAppDashboardHandler } from './miniapp-dashboard'
|
||||
import {
|
||||
createMiniAppApproveMemberHandler,
|
||||
@@ -90,13 +94,13 @@ configureLogger({
|
||||
|
||||
const logger = getLogger('runtime')
|
||||
const shutdownTasks: Array<() => Promise<void>> = []
|
||||
const householdConfigurationRepositoryClient = runtime.databaseUrl
|
||||
? createDbHouseholdConfigurationRepository(runtime.databaseUrl)
|
||||
const workerHouseholdConfigurationRepositoryClient = runtime.workerDatabaseUrl
|
||||
? createDbHouseholdConfigurationRepository(runtime.workerDatabaseUrl)
|
||||
: null
|
||||
const bot = createTelegramBot(
|
||||
runtime.telegramBotToken,
|
||||
getLogger('telegram'),
|
||||
householdConfigurationRepositoryClient?.repository
|
||||
workerHouseholdConfigurationRepositoryClient?.repository
|
||||
)
|
||||
bot.botInfo = await bot.api.getMe()
|
||||
const webhookHandler = webhookCallback(bot, 'std/http', {
|
||||
@@ -111,29 +115,23 @@ const paymentConfirmationServices = new Map<
|
||||
const exchangeRateProvider = createNbgExchangeRateProvider({
|
||||
logger: getLogger('fx')
|
||||
})
|
||||
const householdOnboardingService = householdConfigurationRepositoryClient
|
||||
const householdOnboardingService = workerHouseholdConfigurationRepositoryClient
|
||||
? createHouseholdOnboardingService({
|
||||
repository: householdConfigurationRepositoryClient.repository
|
||||
repository: workerHouseholdConfigurationRepositoryClient.repository
|
||||
})
|
||||
: null
|
||||
const miniAppAdminService = householdConfigurationRepositoryClient
|
||||
? createMiniAppAdminService(householdConfigurationRepositoryClient.repository)
|
||||
: null
|
||||
const localePreferenceService = householdConfigurationRepositoryClient
|
||||
? createLocalePreferenceService(householdConfigurationRepositoryClient.repository)
|
||||
: null
|
||||
const telegramPendingActionRepositoryClient = runtime.databaseUrl
|
||||
? createDbTelegramPendingActionRepository(runtime.databaseUrl!)
|
||||
const telegramPendingActionRepositoryClient = runtime.workerDatabaseUrl
|
||||
? createDbTelegramPendingActionRepository(runtime.workerDatabaseUrl!)
|
||||
: null
|
||||
const processedBotMessageRepositoryClient =
|
||||
runtime.databaseUrl && runtime.assistantEnabled
|
||||
? createDbProcessedBotMessageRepository(runtime.databaseUrl!)
|
||||
runtime.workerDatabaseUrl && runtime.assistantEnabled
|
||||
? createDbProcessedBotMessageRepository(runtime.workerDatabaseUrl!)
|
||||
: null
|
||||
const purchaseRepositoryClient = runtime.databaseUrl
|
||||
? createPurchaseMessageRepository(runtime.databaseUrl!)
|
||||
const purchaseRepositoryClient = runtime.workerDatabaseUrl
|
||||
? createPurchaseMessageRepository(runtime.workerDatabaseUrl!)
|
||||
: null
|
||||
const topicMessageHistoryRepositoryClient = runtime.databaseUrl
|
||||
? createDbTopicMessageHistoryRepository(runtime.databaseUrl!)
|
||||
const topicMessageHistoryRepositoryClient = runtime.workerDatabaseUrl
|
||||
? createDbTopicMessageHistoryRepository(runtime.workerDatabaseUrl!)
|
||||
: null
|
||||
const purchaseInterpreter = createOpenAiPurchaseInterpreter(
|
||||
runtime.openaiApiKey,
|
||||
@@ -169,6 +167,167 @@ const anonymousFeedbackServices = new Map<
|
||||
string,
|
||||
ReturnType<typeof createAnonymousFeedbackService>
|
||||
>()
|
||||
const appHouseholdConfigurationRepositoryClients = new Map<
|
||||
string,
|
||||
ReturnType<typeof createDbHouseholdConfigurationRepository>
|
||||
>()
|
||||
const appOnboardingServices = new Map<string, ReturnType<typeof createHouseholdOnboardingService>>()
|
||||
const appFinanceRepositoryClients = new Map<string, ReturnType<typeof createDbFinanceRepository>>()
|
||||
const appFinanceServices = new Map<string, ReturnType<typeof createFinanceCommandService>>()
|
||||
const appMiniAppAdminServices = new Map<string, ReturnType<typeof createMiniAppAdminService>>()
|
||||
const appLocalePreferenceServices = new Map<
|
||||
string,
|
||||
ReturnType<typeof createLocalePreferenceService>
|
||||
>()
|
||||
|
||||
function miniAppSessionKey(session: MiniAppAuthorizedSession): string {
|
||||
return [
|
||||
session.telegramUserId,
|
||||
session.member.householdId,
|
||||
session.member.id,
|
||||
session.member.isAdmin ? 'admin' : 'member'
|
||||
].join(':')
|
||||
}
|
||||
|
||||
function appHouseholdConfigurationRepositoryKey(input: {
|
||||
telegramUserId: string
|
||||
householdId?: string
|
||||
memberId?: string
|
||||
isAdmin?: boolean
|
||||
}): string {
|
||||
return [
|
||||
input.telegramUserId,
|
||||
input.householdId ?? 'none',
|
||||
input.memberId ?? 'none',
|
||||
input.isAdmin === true ? 'admin' : 'member'
|
||||
].join(':')
|
||||
}
|
||||
|
||||
function appHouseholdConfigurationRepositoryForContext(input: {
|
||||
telegramUserId: string
|
||||
householdId?: string
|
||||
memberId?: string
|
||||
isAdmin?: boolean
|
||||
}) {
|
||||
const key = appHouseholdConfigurationRepositoryKey(input)
|
||||
const existing = appHouseholdConfigurationRepositoryClients.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const repositoryClient = createDbHouseholdConfigurationRepository(runtime.appDatabaseUrl!, {
|
||||
sessionContext: {
|
||||
telegramUserId: input.telegramUserId,
|
||||
...(input.householdId
|
||||
? {
|
||||
householdId: input.householdId
|
||||
}
|
||||
: {}),
|
||||
...(input.memberId
|
||||
? {
|
||||
memberId: input.memberId
|
||||
}
|
||||
: {}),
|
||||
...(input.isAdmin !== undefined
|
||||
? {
|
||||
isAdmin: input.isAdmin
|
||||
}
|
||||
: {})
|
||||
}
|
||||
})
|
||||
appHouseholdConfigurationRepositoryClients.set(key, repositoryClient)
|
||||
shutdownTasks.push(repositoryClient.close)
|
||||
return repositoryClient
|
||||
}
|
||||
|
||||
function appOnboardingServiceForTelegramUserId(telegramUserId: string) {
|
||||
const existing = appOnboardingServices.get(telegramUserId)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const service = createHouseholdOnboardingService({
|
||||
repository: appHouseholdConfigurationRepositoryForContext({
|
||||
telegramUserId
|
||||
}).repository
|
||||
})
|
||||
appOnboardingServices.set(telegramUserId, service)
|
||||
return service
|
||||
}
|
||||
|
||||
function appHouseholdConfigurationRepositoryForSession(session: MiniAppAuthorizedSession) {
|
||||
return appHouseholdConfigurationRepositoryForContext({
|
||||
telegramUserId: session.telegramUserId,
|
||||
householdId: session.member.householdId,
|
||||
memberId: session.member.id,
|
||||
isAdmin: session.member.isAdmin
|
||||
})
|
||||
}
|
||||
|
||||
function appFinanceServiceForSession(session: MiniAppAuthorizedSession) {
|
||||
const key = miniAppSessionKey(session)
|
||||
const existing = appFinanceServices.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const repositoryClient = createDbFinanceRepository(
|
||||
runtime.appDatabaseUrl!,
|
||||
session.member.householdId,
|
||||
{
|
||||
sessionContext: {
|
||||
telegramUserId: session.telegramUserId,
|
||||
householdId: session.member.householdId,
|
||||
memberId: session.member.id,
|
||||
...(session.member.isAdmin !== undefined
|
||||
? {
|
||||
isAdmin: session.member.isAdmin
|
||||
}
|
||||
: {})
|
||||
}
|
||||
}
|
||||
)
|
||||
appFinanceRepositoryClients.set(key, repositoryClient)
|
||||
shutdownTasks.push(repositoryClient.close)
|
||||
|
||||
const service = createFinanceCommandService({
|
||||
householdId: session.member.householdId,
|
||||
repository: repositoryClient.repository,
|
||||
householdConfigurationRepository:
|
||||
appHouseholdConfigurationRepositoryForSession(session).repository,
|
||||
exchangeRateProvider
|
||||
})
|
||||
appFinanceServices.set(key, service)
|
||||
return service
|
||||
}
|
||||
|
||||
function appMiniAppAdminServiceForSession(session: MiniAppAuthorizedSession) {
|
||||
const key = miniAppSessionKey(session)
|
||||
const existing = appMiniAppAdminServices.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const service = createMiniAppAdminService(
|
||||
appHouseholdConfigurationRepositoryForSession(session).repository
|
||||
)
|
||||
appMiniAppAdminServices.set(key, service)
|
||||
return service
|
||||
}
|
||||
|
||||
function appLocalePreferenceServiceForSession(session: MiniAppAuthorizedSession) {
|
||||
const key = miniAppSessionKey(session)
|
||||
const existing = appLocalePreferenceServices.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const service = createLocalePreferenceService(
|
||||
appHouseholdConfigurationRepositoryForSession(session).repository
|
||||
)
|
||||
appLocalePreferenceServices.set(key, service)
|
||||
return service
|
||||
}
|
||||
|
||||
function financeServiceForHousehold(householdId: string) {
|
||||
const existing = financeServices.get(householdId)
|
||||
@@ -180,7 +339,7 @@ function financeServiceForHousehold(householdId: string) {
|
||||
const service = createFinanceCommandService({
|
||||
householdId,
|
||||
repository: repositoryClient.repository,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient!.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient!.repository,
|
||||
exchangeRateProvider
|
||||
})
|
||||
financeServices.set(householdId, service)
|
||||
@@ -193,7 +352,7 @@ function financeRepositoryForHousehold(householdId: string) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const repositoryClient = createDbFinanceRepository(runtime.databaseUrl!, householdId)
|
||||
const repositoryClient = createDbFinanceRepository(runtime.workerDatabaseUrl!, householdId)
|
||||
financeRepositoryClients.set(householdId, repositoryClient)
|
||||
shutdownTasks.push(repositoryClient.close)
|
||||
return repositoryClient
|
||||
@@ -209,7 +368,7 @@ function paymentConfirmationServiceForHousehold(householdId: string) {
|
||||
householdId,
|
||||
financeService: financeServiceForHousehold(householdId),
|
||||
repository: financeRepositoryForHousehold(householdId).repository,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient!.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient!.repository,
|
||||
exchangeRateProvider
|
||||
})
|
||||
paymentConfirmationServices.set(householdId, service)
|
||||
@@ -222,7 +381,10 @@ function anonymousFeedbackServiceForHousehold(householdId: string) {
|
||||
return existing
|
||||
}
|
||||
|
||||
const repositoryClient = createDbAnonymousFeedbackRepository(runtime.databaseUrl!, householdId)
|
||||
const repositoryClient = createDbAnonymousFeedbackRepository(
|
||||
runtime.workerDatabaseUrl!,
|
||||
householdId
|
||||
)
|
||||
anonymousFeedbackRepositoryClients.set(householdId, repositoryClient)
|
||||
shutdownTasks.push(repositoryClient.close)
|
||||
|
||||
@@ -231,8 +393,8 @@ function anonymousFeedbackServiceForHousehold(householdId: string) {
|
||||
return service
|
||||
}
|
||||
|
||||
if (householdConfigurationRepositoryClient) {
|
||||
shutdownTasks.push(householdConfigurationRepositoryClient.close)
|
||||
if (workerHouseholdConfigurationRepositoryClient) {
|
||||
shutdownTasks.push(workerHouseholdConfigurationRepositoryClient.close)
|
||||
}
|
||||
|
||||
if (telegramPendingActionRepositoryClient) {
|
||||
@@ -251,10 +413,10 @@ if (topicMessageHistoryRepositoryClient) {
|
||||
shutdownTasks.push(topicMessageHistoryRepositoryClient.close)
|
||||
}
|
||||
|
||||
if (purchaseRepositoryClient && householdConfigurationRepositoryClient) {
|
||||
if (purchaseRepositoryClient && workerHouseholdConfigurationRepositoryClient) {
|
||||
registerConfiguredPurchaseTopicIngestion(
|
||||
bot,
|
||||
householdConfigurationRepositoryClient.repository,
|
||||
workerHouseholdConfigurationRepositoryClient.repository,
|
||||
purchaseRepositoryClient.repository,
|
||||
{
|
||||
...(topicProcessor
|
||||
@@ -280,7 +442,7 @@ if (purchaseRepositoryClient && householdConfigurationRepositoryClient) {
|
||||
|
||||
registerConfiguredPaymentTopicIngestion(
|
||||
bot,
|
||||
householdConfigurationRepositoryClient.repository,
|
||||
workerHouseholdConfigurationRepositoryClient.repository,
|
||||
telegramPendingActionRepositoryClient!.repository,
|
||||
financeServiceForHousehold,
|
||||
paymentConfirmationServiceForHousehold,
|
||||
@@ -306,13 +468,13 @@ if (purchaseRepositoryClient && householdConfigurationRepositoryClient) {
|
||||
event: 'runtime.feature_disabled',
|
||||
feature: 'purchase-topic-ingestion'
|
||||
},
|
||||
'Purchase topic ingestion is disabled. Set DATABASE_URL to enable Telegram topic lookups.'
|
||||
'Purchase topic ingestion is disabled. Set WORKER_DATABASE_URL to enable Telegram topic lookups.'
|
||||
)
|
||||
}
|
||||
|
||||
if (runtime.financeCommandsEnabled) {
|
||||
const financeCommands = createFinanceCommandsService({
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient!.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient!.repository,
|
||||
financeServiceForHousehold,
|
||||
...(runtime.miniAppUrl
|
||||
? {
|
||||
@@ -329,21 +491,21 @@ if (runtime.financeCommandsEnabled) {
|
||||
event: 'runtime.feature_disabled',
|
||||
feature: 'finance-commands'
|
||||
},
|
||||
'Finance commands are disabled. Set DATABASE_URL to enable household lookups.'
|
||||
'Finance commands are disabled. Set WORKER_DATABASE_URL to enable household lookups.'
|
||||
)
|
||||
}
|
||||
|
||||
if (householdConfigurationRepositoryClient) {
|
||||
if (workerHouseholdConfigurationRepositoryClient) {
|
||||
registerHouseholdSetupCommands({
|
||||
bot,
|
||||
householdSetupService: createHouseholdSetupService(
|
||||
householdConfigurationRepositoryClient.repository
|
||||
workerHouseholdConfigurationRepositoryClient.repository
|
||||
),
|
||||
householdAdminService: createHouseholdAdminService(
|
||||
householdConfigurationRepositoryClient.repository
|
||||
workerHouseholdConfigurationRepositoryClient.repository
|
||||
),
|
||||
householdOnboardingService: householdOnboardingService!,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient.repository,
|
||||
...(telegramPendingActionRepositoryClient
|
||||
? {
|
||||
promptRepository: telegramPendingActionRepositoryClient.repository
|
||||
@@ -362,20 +524,22 @@ if (householdConfigurationRepositoryClient) {
|
||||
event: 'runtime.feature_disabled',
|
||||
feature: 'household-setup'
|
||||
},
|
||||
'Household setup commands are disabled. Set DATABASE_URL to enable.'
|
||||
'Household setup commands are disabled. Set WORKER_DATABASE_URL to enable.'
|
||||
)
|
||||
}
|
||||
|
||||
const reminderJobs = runtime.reminderJobsEnabled
|
||||
? (() => {
|
||||
const reminderRepositoryClient = createDbReminderDispatchRepository(runtime.databaseUrl!)
|
||||
const reminderRepositoryClient = createDbReminderDispatchRepository(
|
||||
runtime.workerDatabaseUrl!
|
||||
)
|
||||
const reminderService = createReminderJobService(reminderRepositoryClient.repository)
|
||||
|
||||
shutdownTasks.push(reminderRepositoryClient.close)
|
||||
|
||||
return createReminderJobsHandler({
|
||||
listReminderTargets: () =>
|
||||
householdConfigurationRepositoryClient!.repository.listReminderTargets(),
|
||||
workerHouseholdConfigurationRepositoryClient!.repository.listReminderTargets(),
|
||||
ensureBillingCycle: async ({ householdId, at }) => {
|
||||
await financeServiceForHousehold(householdId).ensureExpectedCycle(at)
|
||||
},
|
||||
@@ -426,19 +590,19 @@ if (!runtime.reminderJobsEnabled) {
|
||||
event: 'runtime.feature_disabled',
|
||||
feature: 'reminder-jobs'
|
||||
},
|
||||
'Reminder jobs are disabled. Set DATABASE_URL and either SCHEDULER_SHARED_SECRET or SCHEDULER_OIDC_ALLOWED_EMAILS to enable.'
|
||||
'Reminder jobs are disabled. Set WORKER_DATABASE_URL and either SCHEDULER_SHARED_SECRET or SCHEDULER_OIDC_ALLOWED_EMAILS to enable.'
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
runtime.anonymousFeedbackEnabled &&
|
||||
householdConfigurationRepositoryClient &&
|
||||
workerHouseholdConfigurationRepositoryClient &&
|
||||
telegramPendingActionRepositoryClient
|
||||
) {
|
||||
registerAnonymousFeedback({
|
||||
bot,
|
||||
anonymousFeedbackServiceForHousehold,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient!.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient!.repository,
|
||||
promptRepository: telegramPendingActionRepositoryClient!.repository,
|
||||
logger: getLogger('anonymous-feedback')
|
||||
})
|
||||
@@ -448,19 +612,19 @@ if (
|
||||
event: 'runtime.feature_disabled',
|
||||
feature: 'anonymous-feedback'
|
||||
},
|
||||
'Anonymous feedback is disabled. Set DATABASE_URL to enable household and topic lookups.'
|
||||
'Anonymous feedback is disabled. Set WORKER_DATABASE_URL to enable household and topic lookups.'
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
runtime.assistantEnabled &&
|
||||
householdConfigurationRepositoryClient &&
|
||||
workerHouseholdConfigurationRepositoryClient &&
|
||||
telegramPendingActionRepositoryClient
|
||||
) {
|
||||
if (processedBotMessageRepositoryClient) {
|
||||
registerDmAssistant({
|
||||
bot,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient.repository,
|
||||
messageProcessingRepository: processedBotMessageRepositoryClient.repository,
|
||||
promptRepository: telegramPendingActionRepositoryClient.repository,
|
||||
financeServiceForHousehold,
|
||||
@@ -492,7 +656,7 @@ if (
|
||||
} else {
|
||||
registerDmAssistant({
|
||||
bot,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient.repository,
|
||||
promptRepository: telegramPendingActionRepositoryClient.repository,
|
||||
financeServiceForHousehold,
|
||||
memoryStore: assistantMemoryStore,
|
||||
@@ -523,10 +687,10 @@ if (
|
||||
}
|
||||
}
|
||||
|
||||
if (householdConfigurationRepositoryClient && telegramPendingActionRepositoryClient) {
|
||||
if (workerHouseholdConfigurationRepositoryClient && telegramPendingActionRepositoryClient) {
|
||||
registerReminderTopicUtilities({
|
||||
bot,
|
||||
householdConfigurationRepository: householdConfigurationRepositoryClient.repository,
|
||||
householdConfigurationRepository: workerHouseholdConfigurationRepositoryClient.repository,
|
||||
promptRepository: telegramPendingActionRepositoryClient.repository,
|
||||
financeServiceForHousehold,
|
||||
logger: getLogger('reminder-utilities')
|
||||
@@ -537,272 +701,272 @@ const server = createBotWebhookServer({
|
||||
webhookPath: runtime.telegramWebhookPath,
|
||||
webhookSecret: runtime.telegramWebhookSecret,
|
||||
webhookHandler,
|
||||
miniAppAuth: householdOnboardingService
|
||||
miniAppAuth: runtime.miniAppAuthEnabled
|
||||
? createMiniAppAuthHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
logger: getLogger('miniapp-auth')
|
||||
})
|
||||
: undefined,
|
||||
miniAppJoin: householdOnboardingService
|
||||
miniAppJoin: runtime.miniAppAuthEnabled
|
||||
? createMiniAppJoinHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
logger: getLogger('miniapp-auth')
|
||||
})
|
||||
: undefined,
|
||||
miniAppDashboard: householdOnboardingService
|
||||
miniAppDashboard: runtime.miniAppAuthEnabled
|
||||
? createMiniAppDashboardHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
financeServiceForHousehold,
|
||||
onboardingService: householdOnboardingService!,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
logger: getLogger('miniapp-dashboard')
|
||||
})
|
||||
: undefined,
|
||||
miniAppPendingMembers: householdOnboardingService
|
||||
miniAppPendingMembers: runtime.miniAppAuthEnabled
|
||||
? createMiniAppPendingMembersHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppApproveMember: householdOnboardingService
|
||||
miniAppApproveMember: runtime.miniAppAuthEnabled
|
||||
? createMiniAppApproveMemberHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppRejectMember: householdOnboardingService
|
||||
miniAppRejectMember: runtime.miniAppAuthEnabled
|
||||
? createMiniAppRejectMemberHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppSettings: householdOnboardingService
|
||||
miniAppSettings: runtime.miniAppAuthEnabled
|
||||
? createMiniAppSettingsHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
assistantUsageTracker,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateSettings: householdOnboardingService
|
||||
miniAppUpdateSettings: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateSettingsHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpsertUtilityCategory: householdOnboardingService
|
||||
miniAppUpsertUtilityCategory: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpsertUtilityCategoryHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppPromoteMember: householdOnboardingService
|
||||
miniAppPromoteMember: runtime.miniAppAuthEnabled
|
||||
? createMiniAppPromoteMemberHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateOwnDisplayName: householdOnboardingService
|
||||
miniAppUpdateOwnDisplayName: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateOwnDisplayNameHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateMemberDisplayName: householdOnboardingService
|
||||
miniAppUpdateMemberDisplayName: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateMemberDisplayNameHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateMemberRentWeight: householdOnboardingService
|
||||
miniAppUpdateMemberRentWeight: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateMemberRentWeightHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateMemberStatus: householdOnboardingService
|
||||
miniAppUpdateMemberStatus: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateMemberStatusHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateMemberAbsencePolicy: householdOnboardingService
|
||||
miniAppUpdateMemberAbsencePolicy: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateMemberAbsencePolicyHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
miniAppAdminService: miniAppAdminService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
miniAppAdminServiceForSession: appMiniAppAdminServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
miniAppBillingCycle: householdOnboardingService
|
||||
miniAppBillingCycle: runtime.miniAppAuthEnabled
|
||||
? createMiniAppBillingCycleHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppOpenCycle: householdOnboardingService
|
||||
miniAppOpenCycle: runtime.miniAppAuthEnabled
|
||||
? createMiniAppOpenCycleHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppCloseCycle: householdOnboardingService
|
||||
miniAppCloseCycle: runtime.miniAppAuthEnabled
|
||||
? createMiniAppCloseCycleHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppRentUpdate: householdOnboardingService
|
||||
miniAppRentUpdate: runtime.miniAppAuthEnabled
|
||||
? createMiniAppRentUpdateHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppAddUtilityBill: householdOnboardingService
|
||||
miniAppAddUtilityBill: runtime.miniAppAuthEnabled
|
||||
? createMiniAppAddUtilityBillHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppSubmitUtilityBill: householdOnboardingService
|
||||
miniAppSubmitUtilityBill: runtime.miniAppAuthEnabled
|
||||
? createMiniAppSubmitUtilityBillHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdateUtilityBill: householdOnboardingService
|
||||
miniAppUpdateUtilityBill: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdateUtilityBillHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppDeleteUtilityBill: householdOnboardingService
|
||||
miniAppDeleteUtilityBill: runtime.miniAppAuthEnabled
|
||||
? createMiniAppDeleteUtilityBillHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppAddPurchase: householdOnboardingService
|
||||
miniAppAddPurchase: runtime.miniAppAuthEnabled
|
||||
? createMiniAppAddPurchaseHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdatePurchase: householdOnboardingService
|
||||
miniAppUpdatePurchase: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdatePurchaseHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppDeletePurchase: householdOnboardingService
|
||||
miniAppDeletePurchase: runtime.miniAppAuthEnabled
|
||||
? createMiniAppDeletePurchaseHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppAddPayment: householdOnboardingService
|
||||
miniAppAddPayment: runtime.miniAppAuthEnabled
|
||||
? createMiniAppAddPaymentHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppUpdatePayment: householdOnboardingService
|
||||
miniAppUpdatePayment: runtime.miniAppAuthEnabled
|
||||
? createMiniAppUpdatePaymentHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppDeletePayment: householdOnboardingService
|
||||
miniAppDeletePayment: runtime.miniAppAuthEnabled
|
||||
? createMiniAppDeletePaymentHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
financeServiceForHousehold,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
financeServiceForSession: appFinanceServiceForSession,
|
||||
logger: getLogger('miniapp-billing')
|
||||
})
|
||||
: undefined,
|
||||
miniAppLocalePreference: householdOnboardingService
|
||||
miniAppLocalePreference: runtime.miniAppAuthEnabled
|
||||
? createMiniAppLocalePreferenceHandler({
|
||||
allowedOrigins: runtime.miniAppAllowedOrigins,
|
||||
botToken: runtime.telegramBotToken,
|
||||
onboardingService: householdOnboardingService,
|
||||
localePreferenceService: localePreferenceService!,
|
||||
onboardingServiceForTelegramUserId: appOnboardingServiceForTelegramUserId,
|
||||
localePreferenceServiceForSession: appLocalePreferenceServiceForSession,
|
||||
logger: getLogger('miniapp-admin')
|
||||
})
|
||||
: undefined,
|
||||
|
||||
@@ -12,12 +12,59 @@ import type { AssistantUsageTracker } from './dm-assistant'
|
||||
|
||||
import {
|
||||
allowedMiniAppOrigin,
|
||||
type MiniAppAuthorizedSession,
|
||||
createMiniAppSessionService,
|
||||
miniAppErrorResponse,
|
||||
miniAppJsonResponse,
|
||||
readMiniAppRequestPayload
|
||||
} from './miniapp-auth'
|
||||
|
||||
interface MiniAppAdminHandlerBaseOptions {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
miniAppAdminServiceForSession?: (session: MiniAppAuthorizedSession) => MiniAppAdminService
|
||||
miniAppAdminService?: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
function createConfiguredMiniAppSessionService(options: {
|
||||
botToken: string
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
}) {
|
||||
return createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
...(options.onboardingServiceForTelegramUserId
|
||||
? {
|
||||
onboardingServiceForTelegramUserId: options.onboardingServiceForTelegramUserId
|
||||
}
|
||||
: {}),
|
||||
...(options.onboardingService
|
||||
? {
|
||||
onboardingService: options.onboardingService
|
||||
}
|
||||
: {})
|
||||
})
|
||||
}
|
||||
|
||||
function resolveMiniAppAdminService(
|
||||
options: Pick<
|
||||
MiniAppAdminHandlerBaseOptions,
|
||||
'miniAppAdminServiceForSession' | 'miniAppAdminService'
|
||||
>,
|
||||
session: MiniAppAuthorizedSession
|
||||
): MiniAppAdminService {
|
||||
const service = options.miniAppAdminServiceForSession?.(session) ?? options.miniAppAdminService
|
||||
|
||||
if (!service) {
|
||||
throw new Error('Mini app admin service is not configured')
|
||||
}
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
async function readApprovalPayload(request: Request): Promise<{
|
||||
initData: string
|
||||
pendingTelegramUserId: string
|
||||
@@ -401,6 +448,7 @@ async function authenticateAdminSession(
|
||||
| Response
|
||||
| {
|
||||
member: NonNullable<MiniAppSessionResult['member']>
|
||||
telegramUserId: string
|
||||
}
|
||||
> {
|
||||
const payload = await readMiniAppRequestPayload(request)
|
||||
@@ -413,7 +461,7 @@ async function authenticateAdminSession(
|
||||
return miniAppJsonResponse({ ok: false, error: 'Invalid Telegram init data' }, 401, origin)
|
||||
}
|
||||
|
||||
if (!session.authorized || !session.member) {
|
||||
if (!session.authorized || !session.member || !session.telegramUser) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'Admin access required for active household members' },
|
||||
403,
|
||||
@@ -430,23 +478,15 @@ async function authenticateAdminSession(
|
||||
}
|
||||
|
||||
return {
|
||||
member: session.member
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppPendingMembersHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppPendingMembersHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -478,6 +518,7 @@ export function createMiniAppPendingMembersHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -488,7 +529,10 @@ export function createMiniAppPendingMembersHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.listPendingMembers({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).listPendingMembers({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin
|
||||
})
|
||||
@@ -513,20 +557,14 @@ export function createMiniAppPendingMembersHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppSettingsHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
assistantUsageTracker?: AssistantUsageTracker
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppSettingsHandler(
|
||||
options: MiniAppAdminHandlerBaseOptions & {
|
||||
assistantUsageTracker?: AssistantUsageTracker
|
||||
}
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -545,9 +583,12 @@ export function createMiniAppSettingsHandler(options: {
|
||||
if (auth instanceof Response) {
|
||||
return auth
|
||||
}
|
||||
const { member } = auth
|
||||
const { member, telegramUserId } = auth
|
||||
|
||||
const result = await options.miniAppAdminService.getSettings({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member,
|
||||
telegramUserId
|
||||
}).getSettings({
|
||||
householdId: member.householdId,
|
||||
actorIsAdmin: member.isAdmin
|
||||
})
|
||||
@@ -580,19 +621,10 @@ export function createMiniAppSettingsHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateSettingsHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateSettingsHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -623,6 +655,7 @@ export function createMiniAppUpdateSettingsHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -633,7 +666,10 @@ export function createMiniAppUpdateSettingsHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateSettings({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateSettings({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
...(payload.householdName !== undefined
|
||||
@@ -715,19 +751,12 @@ export function createMiniAppUpdateSettingsHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpsertUtilityCategoryHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpsertUtilityCategoryHandler(
|
||||
options: MiniAppAdminHandlerBaseOptions
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -758,6 +787,7 @@ export function createMiniAppUpsertUtilityCategoryHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -768,7 +798,10 @@ export function createMiniAppUpsertUtilityCategoryHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.upsertUtilityCategory({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).upsertUtilityCategory({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
...(payload.slug
|
||||
@@ -811,19 +844,10 @@ export function createMiniAppUpsertUtilityCategoryHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppPromoteMemberHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppPromoteMemberHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -854,6 +878,7 @@ export function createMiniAppPromoteMemberHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -864,7 +889,10 @@ export function createMiniAppPromoteMemberHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.promoteMemberToAdmin({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).promoteMemberToAdmin({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
memberId: payload.memberId
|
||||
@@ -898,19 +926,10 @@ export function createMiniAppPromoteMemberHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateOwnDisplayNameHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateOwnDisplayNameHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -930,7 +949,7 @@ export function createMiniAppUpdateOwnDisplayNameHandler(options: {
|
||||
initData: payload.initData
|
||||
})
|
||||
|
||||
if (!session || !session.authorized || !session.member) {
|
||||
if (!session || !session.authorized || !session.member || !session.telegramUser) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'Active household membership required' },
|
||||
session ? 403 : 401,
|
||||
@@ -938,7 +957,10 @@ export function createMiniAppUpdateOwnDisplayNameHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateOwnDisplayName({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateOwnDisplayName({
|
||||
householdId: session.member.householdId,
|
||||
actorMemberId: session.member.id,
|
||||
displayName: payload.displayName
|
||||
@@ -974,19 +996,12 @@ export function createMiniAppUpdateOwnDisplayNameHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateMemberRentWeightHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateMemberRentWeightHandler(
|
||||
options: MiniAppAdminHandlerBaseOptions
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1017,6 +1032,7 @@ export function createMiniAppUpdateMemberRentWeightHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1027,7 +1043,10 @@ export function createMiniAppUpdateMemberRentWeightHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateMemberRentShareWeight({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateMemberRentShareWeight({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
memberId: payload.memberId,
|
||||
@@ -1070,19 +1089,12 @@ export function createMiniAppUpdateMemberRentWeightHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateMemberDisplayNameHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateMemberDisplayNameHandler(
|
||||
options: MiniAppAdminHandlerBaseOptions
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1106,6 +1118,7 @@ export function createMiniAppUpdateMemberDisplayNameHandler(options: {
|
||||
!session ||
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1120,7 +1133,10 @@ export function createMiniAppUpdateMemberDisplayNameHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing memberId' }, 400, origin)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateMemberDisplayName({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateMemberDisplayName({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
memberId: payload.memberId,
|
||||
@@ -1163,19 +1179,10 @@ export function createMiniAppUpdateMemberDisplayNameHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateMemberStatusHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateMemberStatusHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1199,6 +1206,7 @@ export function createMiniAppUpdateMemberStatusHandler(options: {
|
||||
!session ||
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1209,7 +1217,10 @@ export function createMiniAppUpdateMemberStatusHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateMemberStatus({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateMemberStatus({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
memberId: payload.memberId,
|
||||
@@ -1244,19 +1255,12 @@ export function createMiniAppUpdateMemberStatusHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateMemberAbsencePolicyHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateMemberAbsencePolicyHandler(
|
||||
options: MiniAppAdminHandlerBaseOptions
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1280,6 +1284,7 @@ export function createMiniAppUpdateMemberAbsencePolicyHandler(options: {
|
||||
!session ||
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1290,7 +1295,10 @@ export function createMiniAppUpdateMemberAbsencePolicyHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.updateMemberAbsencePolicy({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).updateMemberAbsencePolicy({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
memberId: payload.memberId,
|
||||
@@ -1325,19 +1333,10 @@ export function createMiniAppUpdateMemberAbsencePolicyHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppApproveMemberHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppApproveMemberHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1368,6 +1367,7 @@ export function createMiniAppApproveMemberHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1378,7 +1378,10 @@ export function createMiniAppApproveMemberHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.approvePendingMember({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).approvePendingMember({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
pendingTelegramUserId: payload.pendingTelegramUserId
|
||||
@@ -1410,19 +1413,10 @@ export function createMiniAppApproveMemberHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppRejectMemberHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
miniAppAdminService: MiniAppAdminService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppRejectMemberHandler(options: MiniAppAdminHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1453,6 +1447,7 @@ export function createMiniAppRejectMemberHandler(options: {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active' ||
|
||||
!session.member.isAdmin
|
||||
) {
|
||||
@@ -1463,7 +1458,10 @@ export function createMiniAppRejectMemberHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.miniAppAdminService.rejectPendingMember({
|
||||
const result = await resolveMiniAppAdminService(options, {
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}).rejectPendingMember({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
pendingTelegramUserId: payload.pendingTelegramUserId
|
||||
|
||||
@@ -115,12 +115,28 @@ export interface MiniAppSessionResult {
|
||||
}
|
||||
}
|
||||
|
||||
export interface MiniAppAuthorizedSession {
|
||||
member: NonNullable<MiniAppSessionResult['member']>
|
||||
telegramUserId: string
|
||||
}
|
||||
|
||||
export function createMiniAppSessionService(options: {
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
}): {
|
||||
authenticate: (payload: MiniAppRequestPayload) => Promise<MiniAppSessionResult | null>
|
||||
} {
|
||||
const resolveOnboardingService =
|
||||
options.onboardingServiceForTelegramUserId ??
|
||||
(() => {
|
||||
if (!options.onboardingService) {
|
||||
throw new Error('Mini app onboarding service is not configured')
|
||||
}
|
||||
|
||||
return options.onboardingService
|
||||
})
|
||||
|
||||
return {
|
||||
authenticate: async (payload) => {
|
||||
if (!payload.initData) {
|
||||
@@ -132,7 +148,7 @@ export function createMiniAppSessionService(options: {
|
||||
return null
|
||||
}
|
||||
|
||||
const access = await options.onboardingService.getMiniAppAccess({
|
||||
const access = await resolveOnboardingService(telegramUser.id).getMiniAppAccess({
|
||||
identity: {
|
||||
telegramUserId: telegramUser.id,
|
||||
displayName:
|
||||
@@ -190,14 +206,24 @@ export function createMiniAppSessionService(options: {
|
||||
export function createMiniAppAuthHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
...(options.onboardingServiceForTelegramUserId
|
||||
? {
|
||||
onboardingServiceForTelegramUserId: options.onboardingServiceForTelegramUserId
|
||||
}
|
||||
: {}),
|
||||
...(options.onboardingService
|
||||
? {
|
||||
onboardingService: options.onboardingService
|
||||
}
|
||||
: {})
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -264,7 +290,8 @@ export function createMiniAppAuthHandler(options: {
|
||||
export function createMiniAppJoinHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
@@ -304,7 +331,13 @@ export function createMiniAppJoinHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await options.onboardingService.joinHousehold({
|
||||
const onboardingService =
|
||||
options.onboardingServiceForTelegramUserId?.(telegramUser.id) ?? options.onboardingService
|
||||
if (!onboardingService) {
|
||||
throw new Error('Mini app onboarding service is not configured')
|
||||
}
|
||||
|
||||
const result = await onboardingService.joinHousehold({
|
||||
identity: {
|
||||
telegramUserId: telegramUser.id,
|
||||
displayName:
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { FinanceCommandService, HouseholdOnboardingService } from '@househo
|
||||
import { BillingPeriod } from '@household/domain'
|
||||
import type { Logger } from '@household/observability'
|
||||
import type { HouseholdConfigurationRepository } from '@household/ports'
|
||||
import type { MiniAppSessionResult } from './miniapp-auth'
|
||||
import type { MiniAppAuthorizedSession, MiniAppSessionResult } from './miniapp-auth'
|
||||
|
||||
import {
|
||||
allowedMiniAppOrigin,
|
||||
@@ -12,6 +12,54 @@ import {
|
||||
readMiniAppRequestPayload
|
||||
} from './miniapp-auth'
|
||||
|
||||
interface MiniAppBillingHandlerBaseOptions {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForSession?: (session: MiniAppAuthorizedSession) => FinanceCommandService
|
||||
financeServiceForHousehold?: (householdId: string) => FinanceCommandService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
function createConfiguredMiniAppBillingSessionService(options: {
|
||||
botToken: string
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
}) {
|
||||
return createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
...(options.onboardingServiceForTelegramUserId
|
||||
? {
|
||||
onboardingServiceForTelegramUserId: options.onboardingServiceForTelegramUserId
|
||||
}
|
||||
: {}),
|
||||
...(options.onboardingService
|
||||
? {
|
||||
onboardingService: options.onboardingService
|
||||
}
|
||||
: {})
|
||||
})
|
||||
}
|
||||
|
||||
function resolveFinanceService(
|
||||
options: Pick<
|
||||
MiniAppBillingHandlerBaseOptions,
|
||||
'financeServiceForSession' | 'financeServiceForHousehold'
|
||||
>,
|
||||
session: MiniAppAuthorizedSession
|
||||
): FinanceCommandService {
|
||||
const service =
|
||||
options.financeServiceForSession?.(session) ??
|
||||
options.financeServiceForHousehold?.(session.member.householdId)
|
||||
|
||||
if (!service) {
|
||||
throw new Error('Mini app finance service is not configured')
|
||||
}
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
function serializeCycleState(
|
||||
state: Awaited<ReturnType<FinanceCommandService['getAdminCycleState']>>
|
||||
) {
|
||||
@@ -42,6 +90,7 @@ async function authenticateAdminSession(
|
||||
| Response
|
||||
| {
|
||||
member: NonNullable<MiniAppSessionResult['member']>
|
||||
telegramUserId: string
|
||||
}
|
||||
> {
|
||||
const payload = await readMiniAppRequestPayload(request)
|
||||
@@ -54,7 +103,7 @@ async function authenticateAdminSession(
|
||||
return miniAppJsonResponse({ ok: false, error: 'Invalid Telegram init data' }, 401, origin)
|
||||
}
|
||||
|
||||
if (!session.authorized || !session.member) {
|
||||
if (!session.authorized || !session.member || !session.telegramUser) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'Access limited to active household members' },
|
||||
403,
|
||||
@@ -67,7 +116,8 @@ async function authenticateAdminSession(
|
||||
}
|
||||
|
||||
return {
|
||||
member: session.member
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +129,7 @@ async function authenticateMemberSession(
|
||||
| Response
|
||||
| {
|
||||
member: NonNullable<MiniAppSessionResult['member']>
|
||||
telegramUserId: string
|
||||
}
|
||||
> {
|
||||
const payload = await readMiniAppRequestPayload(request)
|
||||
@@ -91,7 +142,12 @@ async function authenticateMemberSession(
|
||||
return miniAppJsonResponse({ ok: false, error: 'Invalid Telegram init data' }, 401, origin)
|
||||
}
|
||||
|
||||
if (!session.authorized || !session.member || session.member.status !== 'active') {
|
||||
if (
|
||||
!session.authorized ||
|
||||
!session.member ||
|
||||
!session.telegramUser ||
|
||||
session.member.status !== 'active'
|
||||
) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'Access limited to active household members' },
|
||||
403,
|
||||
@@ -100,7 +156,8 @@ async function authenticateMemberSession(
|
||||
}
|
||||
|
||||
return {
|
||||
member: session.member
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,19 +587,10 @@ async function readPaymentMutationPayload(request: Request): Promise<{
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppBillingCycleHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppBillingCycleHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -567,9 +615,9 @@ export function createMiniAppBillingCycleHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readCycleQueryPayload(request)
|
||||
const cycleState = await options
|
||||
.financeServiceForHousehold(auth.member.householdId)
|
||||
.getAdminCycleState(payload.period)
|
||||
const cycleState = await resolveFinanceService(options, auth).getAdminCycleState(
|
||||
payload.period
|
||||
)
|
||||
|
||||
return miniAppJsonResponse(
|
||||
{
|
||||
@@ -587,19 +635,10 @@ export function createMiniAppBillingCycleHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppOpenCycleHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppOpenCycleHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -624,7 +663,7 @@ export function createMiniAppOpenCycleHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readOpenCyclePayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
await service.openCycle(payload.period, payload.currency)
|
||||
const cycleState = await service.getAdminCycleState(payload.period)
|
||||
|
||||
@@ -644,19 +683,10 @@ export function createMiniAppOpenCycleHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppCloseCycleHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppCloseCycleHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -681,7 +711,7 @@ export function createMiniAppCloseCycleHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readCycleQueryPayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
await service.closeCycle(payload.period)
|
||||
const cycleState = await service.getAdminCycleState()
|
||||
|
||||
@@ -701,19 +731,10 @@ export function createMiniAppCloseCycleHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppRentUpdateHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppRentUpdateHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -738,7 +759,7 @@ export function createMiniAppRentUpdateHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readRentUpdatePayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const result = await service.setRent(payload.amountMajor, payload.currency, payload.period)
|
||||
if (!result) {
|
||||
return miniAppJsonResponse(
|
||||
@@ -766,19 +787,10 @@ export function createMiniAppRentUpdateHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppAddUtilityBillHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppAddUtilityBillHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -803,7 +815,7 @@ export function createMiniAppAddUtilityBillHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readUtilityBillPayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const result = await service.addUtilityBill(
|
||||
payload.billName,
|
||||
payload.amountMajor,
|
||||
@@ -837,19 +849,10 @@ export function createMiniAppAddUtilityBillHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppSubmitUtilityBillHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppSubmitUtilityBillHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -874,7 +877,7 @@ export function createMiniAppSubmitUtilityBillHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readUtilityBillPayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const result = await service.addUtilityBill(
|
||||
payload.billName,
|
||||
payload.amountMajor,
|
||||
@@ -905,35 +908,33 @@ export function createMiniAppSubmitUtilityBillHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppSubmitPaymentHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
householdConfigurationRepository: HouseholdConfigurationRepository
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppSubmitPaymentHandler(
|
||||
options: MiniAppBillingHandlerBaseOptions & {
|
||||
householdConfigurationRepositoryForSession: (
|
||||
session: MiniAppAuthorizedSession
|
||||
) => HouseholdConfigurationRepository
|
||||
}
|
||||
): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
async function notifyPaymentRecorded(input: {
|
||||
householdId: string
|
||||
memberName: string
|
||||
kind: 'rent' | 'utilities'
|
||||
amountMajor: string
|
||||
currency: string
|
||||
period: string
|
||||
}) {
|
||||
async function notifyPaymentRecorded(
|
||||
session: MiniAppAuthorizedSession,
|
||||
input: {
|
||||
householdId: string
|
||||
memberName: string
|
||||
kind: 'rent' | 'utilities'
|
||||
amountMajor: string
|
||||
currency: string
|
||||
period: string
|
||||
}
|
||||
) {
|
||||
const householdConfigurationRepository =
|
||||
options.householdConfigurationRepositoryForSession(session)
|
||||
const [chat, topic] = await Promise.all([
|
||||
options.householdConfigurationRepository.getHouseholdChatByHouseholdId(input.householdId),
|
||||
options.householdConfigurationRepository.getHouseholdTopicBinding(
|
||||
input.householdId,
|
||||
'reminders'
|
||||
)
|
||||
householdConfigurationRepository.getHouseholdChatByHouseholdId(input.householdId),
|
||||
householdConfigurationRepository.getHouseholdTopicBinding(input.householdId, 'reminders')
|
||||
])
|
||||
|
||||
if (!chat || !topic) {
|
||||
@@ -996,7 +997,7 @@ export function createMiniAppSubmitPaymentHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing payment fields' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const payment = await service.addPayment(
|
||||
auth.member.id,
|
||||
payload.kind,
|
||||
@@ -1008,7 +1009,7 @@ export function createMiniAppSubmitPaymentHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Failed to record payment' }, 500, origin)
|
||||
}
|
||||
|
||||
await notifyPaymentRecorded({
|
||||
await notifyPaymentRecorded(auth, {
|
||||
householdId: auth.member.householdId,
|
||||
memberName: auth.member.displayName,
|
||||
kind: payload.kind,
|
||||
@@ -1032,19 +1033,10 @@ export function createMiniAppSubmitPaymentHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdateUtilityBillHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdateUtilityBillHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1069,7 +1061,7 @@ export function createMiniAppUpdateUtilityBillHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readUtilityBillUpdatePayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const result = await service.updateUtilityBill(
|
||||
payload.billId,
|
||||
payload.billName,
|
||||
@@ -1099,19 +1091,10 @@ export function createMiniAppUpdateUtilityBillHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppDeleteUtilityBillHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppDeleteUtilityBillHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1136,7 +1119,7 @@ export function createMiniAppDeleteUtilityBillHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readUtilityBillDeletePayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const deleted = await service.deleteUtilityBill(payload.billId)
|
||||
|
||||
if (!deleted) {
|
||||
@@ -1161,19 +1144,10 @@ export function createMiniAppDeleteUtilityBillHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppAddPurchaseHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppAddPurchaseHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1200,7 +1174,7 @@ export function createMiniAppAddPurchaseHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing purchase fields' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const payerMemberId = payload.payerMemberId ?? auth.member.id
|
||||
await service.addPurchase(
|
||||
payload.description,
|
||||
@@ -1218,19 +1192,10 @@ export function createMiniAppAddPurchaseHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdatePurchaseHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdatePurchaseHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1257,7 +1222,7 @@ export function createMiniAppUpdatePurchaseHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing purchase fields' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const payerMemberId = payload.payerMemberId
|
||||
const updated = await service.updatePurchase(
|
||||
payload.purchaseId,
|
||||
@@ -1280,19 +1245,10 @@ export function createMiniAppUpdatePurchaseHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppDeletePurchaseHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppDeletePurchaseHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1315,7 +1271,7 @@ export function createMiniAppDeletePurchaseHandler(options: {
|
||||
}
|
||||
|
||||
const payload = await readPurchaseMutationPayload(request)
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const deleted = await service.deletePurchase(payload.purchaseId)
|
||||
|
||||
if (!deleted) {
|
||||
@@ -1330,19 +1286,10 @@ export function createMiniAppDeletePurchaseHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppAddPaymentHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppAddPaymentHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1369,7 +1316,7 @@ export function createMiniAppAddPaymentHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing payment fields' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const payment = await service.addPayment(
|
||||
payload.memberId,
|
||||
payload.kind,
|
||||
@@ -1389,19 +1336,10 @@ export function createMiniAppAddPaymentHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppUpdatePaymentHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppUpdatePaymentHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1428,7 +1366,7 @@ export function createMiniAppUpdatePaymentHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing payment fields' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const payment = await service.updatePayment(
|
||||
payload.paymentId,
|
||||
payload.memberId,
|
||||
@@ -1449,19 +1387,10 @@ export function createMiniAppUpdatePaymentHandler(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMiniAppDeletePaymentHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
export function createMiniAppDeletePaymentHandler(options: MiniAppBillingHandlerBaseOptions): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
})
|
||||
const sessionService = createConfiguredMiniAppBillingSessionService(options)
|
||||
|
||||
return {
|
||||
handler: async (request) => {
|
||||
@@ -1488,7 +1417,7 @@ export function createMiniAppDeletePaymentHandler(options: {
|
||||
return miniAppJsonResponse({ ok: false, error: 'Missing payment id' }, 400, origin)
|
||||
}
|
||||
|
||||
const service = options.financeServiceForHousehold(auth.member.householdId)
|
||||
const service = resolveFinanceService(options, auth)
|
||||
const deleted = await service.deletePayment(payload.paymentId)
|
||||
|
||||
if (!deleted) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Logger } from '@household/observability'
|
||||
|
||||
import {
|
||||
allowedMiniAppOrigin,
|
||||
type MiniAppAuthorizedSession,
|
||||
createMiniAppSessionService,
|
||||
miniAppErrorResponse,
|
||||
miniAppJsonResponse,
|
||||
@@ -12,15 +13,26 @@ import {
|
||||
export function createMiniAppDashboardHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
financeServiceForHousehold: (householdId: string) => FinanceCommandService
|
||||
onboardingService: HouseholdOnboardingService
|
||||
financeServiceForSession?: (session: MiniAppAuthorizedSession) => FinanceCommandService
|
||||
financeServiceForHousehold?: (householdId: string) => FinanceCommandService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
logger?: Logger
|
||||
}): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
...(options.onboardingServiceForTelegramUserId
|
||||
? {
|
||||
onboardingServiceForTelegramUserId: options.onboardingServiceForTelegramUserId
|
||||
}
|
||||
: {}),
|
||||
...(options.onboardingService
|
||||
? {
|
||||
onboardingService: options.onboardingService
|
||||
}
|
||||
: {})
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -62,7 +74,7 @@ export function createMiniAppDashboardHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
if (!session.member) {
|
||||
if (!session.member || !session.telegramUser) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'Authenticated session is missing member context' },
|
||||
500,
|
||||
@@ -70,9 +82,17 @@ export function createMiniAppDashboardHandler(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const dashboard = await options
|
||||
.financeServiceForHousehold(session.member.householdId)
|
||||
.generateDashboard()
|
||||
const financeService =
|
||||
options.financeServiceForSession?.({
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}) ?? options.financeServiceForHousehold?.(session.member.householdId)
|
||||
|
||||
if (!financeService) {
|
||||
throw new Error('Mini app finance service is not configured')
|
||||
}
|
||||
|
||||
const dashboard = await financeService.generateDashboard()
|
||||
if (!dashboard) {
|
||||
return miniAppJsonResponse(
|
||||
{ ok: false, error: 'No billing cycle available' },
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Logger } from '@household/observability'
|
||||
|
||||
import {
|
||||
allowedMiniAppOrigin,
|
||||
type MiniAppAuthorizedSession,
|
||||
createMiniAppSessionService,
|
||||
miniAppErrorResponse,
|
||||
miniAppJsonResponse
|
||||
@@ -53,15 +54,26 @@ async function readLocalePreferenceRequest(request: Request): Promise<LocalePref
|
||||
export function createMiniAppLocalePreferenceHandler(options: {
|
||||
allowedOrigins: readonly string[]
|
||||
botToken: string
|
||||
onboardingService: HouseholdOnboardingService
|
||||
localePreferenceService: LocalePreferenceService
|
||||
onboardingServiceForTelegramUserId?: (telegramUserId: string) => HouseholdOnboardingService
|
||||
onboardingService?: HouseholdOnboardingService
|
||||
localePreferenceServiceForSession?: (session: MiniAppAuthorizedSession) => LocalePreferenceService
|
||||
localePreferenceService?: LocalePreferenceService
|
||||
logger?: Logger
|
||||
}): {
|
||||
handler: (request: Request) => Promise<Response>
|
||||
} {
|
||||
const sessionService = createMiniAppSessionService({
|
||||
botToken: options.botToken,
|
||||
onboardingService: options.onboardingService
|
||||
...(options.onboardingServiceForTelegramUserId
|
||||
? {
|
||||
onboardingServiceForTelegramUserId: options.onboardingServiceForTelegramUserId
|
||||
}
|
||||
: {}),
|
||||
...(options.onboardingService
|
||||
? {
|
||||
onboardingService: options.onboardingService
|
||||
}
|
||||
: {})
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -100,9 +112,18 @@ export function createMiniAppLocalePreferenceHandler(options: {
|
||||
|
||||
let memberPreferredLocale = session.member.preferredLocale
|
||||
let householdDefaultLocale = session.member.householdDefaultLocale
|
||||
const localePreferenceService =
|
||||
options.localePreferenceServiceForSession?.({
|
||||
member: session.member,
|
||||
telegramUserId: session.telegramUser.id
|
||||
}) ?? options.localePreferenceService
|
||||
|
||||
if (!localePreferenceService) {
|
||||
throw new Error('Mini app locale preference service is not configured')
|
||||
}
|
||||
|
||||
if (payload.scope === 'member') {
|
||||
const result = await options.localePreferenceService.updateMemberLocale({
|
||||
const result = await localePreferenceService.updateMemberLocale({
|
||||
householdId: session.member.householdId,
|
||||
telegramUserId: session.telegramUser.id,
|
||||
locale: payload.locale
|
||||
@@ -115,7 +136,7 @@ export function createMiniAppLocalePreferenceHandler(options: {
|
||||
memberPreferredLocale = result.member.preferredLocale
|
||||
householdDefaultLocale = result.member.householdDefaultLocale
|
||||
} else {
|
||||
const result = await options.localePreferenceService.updateHouseholdLocale({
|
||||
const result = await localePreferenceService.updateHouseholdLocale({
|
||||
householdId: session.member.householdId,
|
||||
actorIsAdmin: session.member.isAdmin,
|
||||
locale: payload.locale
|
||||
|
||||
Reference in New Issue
Block a user