Files
property-match/src/services/authService.ts
T
Benjamin Sutter efc72b720e fix: P0 stabilisation — score modifiers, logout cache clear, provider isolation, mutation error feedback
- scoreCalculator: apply dataQuality/confidence modifiers to finalScore (were computed but hardcoded to 0)
- authService: call queryClient.clear() on logout to prevent cross-session data leakage
- queryClient: extract to src/lib/queryClient.ts singleton so services can access it without circular imports
- matchSyncService: new service layer owns match-generation logic; MockupNeedProvider no longer imports other providers directly
- hooks (11 files): add onError + German toast feedback to every useMutation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:13:14 +02:00

137 lines
4.6 KiB
TypeScript

import { useSessionStore } from '../stores/sessionStore'
import type { MockUser } from '../stores/sessionStore'
import type { ItemResponse } from './types'
import { UserRole, WorkspaceType } from '../domain/enums'
import { getPermissions, getAccessibleWorkspaces } from '../lib/permissions'
import type { Permission } from '../lib/permissions'
import { queryClient } from '../lib/queryClient'
// Mock organizations for org switching
const MOCK_ORGANIZATIONS: { id: string; name: string }[] = [
{ id: 'org-wincasa', name: 'Wincasa AG' },
{ id: 'org-mobimo', name: 'Mobimo Management AG' },
{ id: 'org-ubs', name: 'UBS Asset Management RE' },
]
// Demo user presets per role
const DEMO_USERS: Record<UserRole, MockUser> = {
[UserRole.SUPER_ADMIN]: {
id: 'user-super',
email: 'super@ideal-sharing.ch',
name: 'Super Admin',
role: UserRole.SUPER_ADMIN,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: [WorkspaceType.SUPPLY, WorkspaceType.DEMAND],
},
[UserRole.ORGANIZATION_ADMIN]: {
id: 'user-001',
email: 'admin@ideal-sharing.ch',
name: 'Admin User',
role: UserRole.ORGANIZATION_ADMIN,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: [WorkspaceType.SUPPLY, WorkspaceType.DEMAND],
},
[UserRole.PROPERTY_MANAGER]: {
id: 'user-pm',
email: 'pm@ideal-sharing.ch',
name: 'Property Manager',
role: UserRole.PROPERTY_MANAGER,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: getAccessibleWorkspaces(UserRole.PROPERTY_MANAGER),
},
[UserRole.REVIEWER]: {
id: 'user-rev',
email: 'reviewer@ideal-sharing.ch',
name: 'Reviewer',
role: UserRole.REVIEWER,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: getAccessibleWorkspaces(UserRole.REVIEWER),
},
[UserRole.OWNER_VIEWER]: {
id: 'user-ov',
email: 'owner@ideal-sharing.ch',
name: 'Owner Viewer',
role: UserRole.OWNER_VIEWER,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: getAccessibleWorkspaces(UserRole.OWNER_VIEWER),
},
[UserRole.DEMAND_USER]: {
id: 'user-dem',
email: 'demand@ideal-sharing.ch',
name: 'Demand User',
role: UserRole.DEMAND_USER,
organizationId: 'org-mobimo',
organizationName: 'Mobimo Management AG',
allowedWorkspaces: getAccessibleWorkspaces(UserRole.DEMAND_USER),
},
}
export const authService = {
async getCurrentUser(): Promise<ItemResponse<MockUser | null>> {
const data = useSessionStore.getState().currentUser
return { data }
},
async getCurrentOrganization(): Promise<ItemResponse<{ id: string; name: string } | null>> {
const { activeOrganizationId } = useSessionStore.getState()
const org = MOCK_ORGANIZATIONS.find((o) => o.id === activeOrganizationId) ?? null
return { data: org }
},
async login(email: string, _password: string): Promise<ItemResponse<MockUser>> {
const existing = Object.values(DEMO_USERS).find((u) => u.email === email)
const user: MockUser = existing ?? {
id: 'user-001',
email,
name: 'Admin User',
role: UserRole.ORGANIZATION_ADMIN,
organizationId: 'org-wincasa',
organizationName: 'Wincasa AG',
allowedWorkspaces: [WorkspaceType.SUPPLY, WorkspaceType.DEMAND],
}
useSessionStore.getState().login(user)
return { data: user }
},
async logout(): Promise<ItemResponse<void>> {
useSessionStore.getState().logout()
// Clear all cached query data so stale data from the previous session
// cannot leak to the next user who logs in on the same browser tab.
queryClient.clear()
return { data: undefined }
},
async isAuthenticated(): Promise<ItemResponse<boolean>> {
const data = useSessionStore.getState().isAuthenticated
return { data }
},
async switchDemoRole(role: UserRole): Promise<ItemResponse<MockUser>> {
const user = DEMO_USERS[role]
useSessionStore.getState().login(user)
return { data: user }
},
async switchOrganization(organizationId: string): Promise<ItemResponse<void>> {
const org = MOCK_ORGANIZATIONS.find((o) => o.id === organizationId)
if (org) {
const state = useSessionStore.getState()
if (state.currentUser) {
state.login({ ...state.currentUser, organizationId: org.id, organizationName: org.name })
} else {
state.switchOrganization(organizationId)
}
}
return { data: undefined }
},
async getPermissions(user: MockUser): Promise<ItemResponse<Permission[]>> {
return { data: getPermissions(user) }
},
}