import { errors, Notification, Plan, Tenant, UserData, tenantRole, } from "@kumori/aurora-interfaces"; interface HandleUserEventParams { eventData: any; tenantsMap: Map; currentUserData: UserData; currentUserNotifications: Notification[]; plansMap: Map; parseKeyPath: (key: string) => { [entity: string]: string }; eventHelper: any; } interface HandleUserEventResult { userData: UserData; tempProviders: Record; deletedTenantKeys: string[]; } /** * Handles the "user" event from WebSocket messages * Processes user data updates, tenant deletions, and plan assignments */ export const handleUserEvent = ({ eventData, tenantsMap, currentUserData, currentUserNotifications, plansMap, parseKeyPath, eventHelper, }: HandleUserEventParams): HandleUserEventResult => { const userId = eventData.id.name; const userTenants = Object.keys(eventData.status.tenants); const deletedTenantKeys: string[] = []; for (const key of tenantsMap.keys()) { if (!userTenants.includes(key)) { const tenantToDelete = tenantsMap.get(key); if (tenantToDelete) { const currentUserInTenant = tenantToDelete.users.find( (u) => u.id === userId, ); const isRejectedOrLeaving = currentUserInTenant?.status === "rejected" || tenantToDelete.status === "leaving"; if (currentUserInTenant && !isRejectedOrLeaving) { const onlyOneUser = tenantToDelete.users.length === 1; const isSoloOwner = onlyOneUser && currentUserInTenant.role === tenantRole.OWNER && currentUserInTenant.id === userId; if (isSoloOwner) { eventHelper.tenant.publish.deleted(tenantToDelete); const tenantDeletedNotification: Notification = { type: "success", subtype: errors.tenant.deleted.subtype, date: Date.now().toString(), callToAction: false, status: "unread", data: { tenant: tenantToDelete.name, }, }; eventHelper.notification.publish.creation( tenantDeletedNotification, ); } else { const userRemovedNotification: Notification = { type: "info", subtype: errors.tenant.accessRevoked.subtype, date: Date.now().toString(), callToAction: false, status: "unread", data: { tenant: tenantToDelete.name, }, }; eventHelper.notification.publish.creation(userRemovedNotification); } } deletedTenantKeys.push(key); } } } const existingNotifications = currentUserData.notifications || currentUserNotifications || []; const userPlans: Plan[] = []; if (eventData.spec.plans) { Object.entries(eventData.spec.plans).forEach( ([planPath, role]: [string, any]) => { const planPathParts = parseKeyPath(planPath); const planProvider = planPathParts.planprovider; const planInstance = planPathParts.planinstance; const planKey = `${planProvider}/${planInstance}`; const plan = plansMap.get(planKey); if (plan) { userPlans.push({ ...plan, }); } else { const basicPlan: Plan = { name: planInstance, provider: planProvider, }; userPlans.push(basicPlan); } }, ); } const tempProviders: Record = eventData.spec.providers || {}; const providers: { name: string; email: string; password?: string }[] = []; const existingProvidersMap = new Map( (currentUserData.provider || []).map((p) => [p.name, p]), ); for (const [providerName, providerId] of Object.entries(tempProviders)) { const existingProvider = existingProvidersMap.get(providerName); if (existingProvider && existingProvider.email) { providers.push(existingProvider); } else { providers.push({ name: providerName, email: existingProvider?.email || "", }); } } const userData: UserData = { id: userId, name: eventData.spec.userinfo.name, surname: eventData.spec.userinfo.surname, provider: providers, notificationsEnabled: "", organizations: [], clusterTokens: [], tokens: [], tenants: [], axebowPlan: "freemium", companyName: eventData.spec.userinfo.companyName, rol: eventData.spec.userinfo.companyRole, notifications: existingNotifications, plans: userPlans, discoveryMethod: eventData.spec.userinfo.discoveryMethod, }; return { userData, tempProviders, deletedTenantKeys, }; }; export const handleUserOperationError = (): UserData => { return { id: "", name: "", surname: "", provider: [], notificationsEnabled: "", organizations: [], clusterTokens: [], tokens: [], tenants: [], axebowPlan: "freemium", companyName: "", rol: "", }; };