import { CustomEpic, actionTypes, AnyAction } from '../interfaces/actions' import { getBasicAuthRequest } from '../api/session' import { LoginResponse } from '@tesler-ui/core/interfaces/session' import { Observable } from 'rxjs/Observable' import { $do, SSO_AUTH } from '../actions/types' import { AxiosError } from 'axios' import { AppState } from "../interfaces/storeSlices"; import { Epic } from "redux-observable"; import { keycloak, keycloakOptions } from '../keycloak' const responseStatusMessages: Record = { 401: 'Unauthorized', 403: 'Access denied' } const ssoAuthEpic: Epic = (action$, store) => action$.ofType(SSO_AUTH).switchMap(() => { return Observable.fromPromise(keycloak.init(keycloakOptions)) .switchMap(() => Observable.of($do.login({ login: '', password: '' }))) .catch(() => { console.error('Authentication failed') return Observable.empty() }) }) const loginEpic: CustomEpic = (action$, store) => action$.ofType(actionTypes.login) .filter(action => !action.payload?.role) .switchMap((action) => { const login = action.payload && action.payload.login const password = action.payload && action.payload.password return getBasicAuthRequest(login, password) .mergeMap((data: LoginResponse) => { return Observable.of($do.loginDone({ devPanelEnabled: data.devPanelEnabled, activeRole: data.activeRole, roles: data.roles, firstName: data.firstName, lastName: data.lastName, login: data.login, screens: data.screens })) }) .catch((error: AxiosError) => { const errorMsg = (error.response) ? responseStatusMessages[error.response.status] || 'Server application unavailable' : 'Empty response from server' return Observable.of($do.loginFail({ errorMsg })) }) }) const logoutEpic: CustomEpic = (action$, store) => action$.ofType(actionTypes.logout).switchMap(() => { keycloak.logout() return Observable.of($do.logoutDone(null)) }) const logoutDone: CustomEpic = (action$, store) => action$.ofType(actionTypes.logoutDone).switchMap(() => { return Observable.empty() }) export const sessionEpics = { ssoAuthEpic, logoutEpic, logoutDone, loginEpic }