diff options
Diffstat (limited to 'sdnr/wt/odlux/framework')
-rw-r--r-- | sdnr/wt/odlux/framework/package.json | 2 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/pom.xml | 6 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/actions/authentication.ts | 78 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/actions/settingsAction.ts | 8 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/components/navigationMenu.tsx | 2 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts | 2 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/middleware/navigation.ts | 65 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/models/settings.ts | 39 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/applicationApi.ts | 20 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/broadcastService.ts | 45 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/index.ts | 2 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/restService.ts | 57 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/userdataService.ts | 21 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/views/about.tsx | 6 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/views/frame.tsx | 7 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src2/main/resources/version.json | 2 |
16 files changed, 184 insertions, 178 deletions
diff --git a/sdnr/wt/odlux/framework/package.json b/sdnr/wt/odlux/framework/package.json index 6ea08412e..9973d3b7c 100644 --- a/sdnr/wt/odlux/framework/package.json +++ b/sdnr/wt/odlux/framework/package.json @@ -29,6 +29,7 @@ "@fortawesome/react-fontawesome": "0.1.14",
"@types/classnames": "2.2.6",
"@types/flux": "3.1.8",
+ "@types/history": "^4.7.9",
"@types/jquery": "3.3.10",
"@types/jsonwebtoken": "7.2.8",
"@types/node": "^12.0.0",
@@ -36,6 +37,7 @@ "@types/react-dom": "17.0.11",
"@types/react-router-dom": "5.1.7",
"jquery": "3.3.1",
+ "history": "^4.9.0",
"jsonwebtoken": "8.3.0",
"react": "17.0.2",
"react-dom": "17.0.2",
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml index 315343b59..d0dee60a8 100644 --- a/sdnr/wt/odlux/framework/pom.xml +++ b/sdnr/wt/odlux/framework/pom.xml @@ -45,7 +45,7 @@ <properties> <buildtime>${maven.build.timestamp}</buildtime> <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion> - <buildno>178.3bd8a2a9(23/03/16)</buildno> + <buildno>188.1b12eac8(23/06/30)</buildno> <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version> </properties> @@ -102,8 +102,8 @@ <!-- optional: default phase is "generate-resources" --> <phase>initialize</phase> <configuration> - <nodeVersion>v12.22.0</nodeVersion> - <yarnVersion>v1.22.10</yarnVersion> + <nodeVersion>v16.17.0</nodeVersion> + <yarnVersion>v1.22.19</yarnVersion> </configuration> </execution> <execution> diff --git a/sdnr/wt/odlux/framework/src/actions/authentication.ts b/sdnr/wt/odlux/framework/src/actions/authentication.ts index f1d11de37..141249530 100644 --- a/sdnr/wt/odlux/framework/src/actions/authentication.ts +++ b/sdnr/wt/odlux/framework/src/actions/authentication.ts @@ -18,80 +18,90 @@ import { Dispatch } from '../flux/store'; import { Action } from '../flux/action'; import { AuthPolicy, User } from '../models/authentication'; -import { GeneralSettings, Settings } from '../models/settings'; -import { saveInitialSettings, SetGeneralSettingsAction, setGeneralSettingsAction } from './settingsAction'; +import { Settings } from '../models/settings'; +import { saveInitialSettings, SetGeneralSettingsAction } from './settingsAction'; import { endWebsocketSession } from '../services/notificationService'; import { endUserSession, startUserSession } from '../services/userSessionService'; import { IApplicationStoreState } from '../store/applicationStore'; export class UpdateUser extends Action { - constructor (public user?: User) { + constructor(public user?: User) { super(); } } export class UpdatePolicies extends Action { - constructor (public authPolicies?: AuthPolicy[]) { + constructor(public authPolicies?: AuthPolicy[]) { super(); } } - -export const loginUserAction = (user?: User) => (dispatcher: Dispatch) =>{ - - dispatcher(new UpdateUser(user)); - if(user){ - startUserSession(user); - loadUserSettings(user, dispatcher); - localStorage.setItem("userToken", user.toString()); - } -} - export const logoutUser = () => (dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{ - const {framework:{applicationState:{ authentication }, authenticationState: {user}}} = getState(); + const { framework:{ applicationState:{ authentication }, authenticationState: { user } } } = getState(); dispatcher(new UpdateUser(undefined)); dispatcher(new SetGeneralSettingsAction(null)); endWebsocketSession(); endUserSession(); - localStorage.removeItem("userToken"); + localStorage.removeItem('userToken'); //only call if a user is currently logged in - if (authentication === "oauth" && user) { + if (authentication === 'oauth' && user) { const url = window.location.origin; - window.location.href=`${url}/oauth/logout`; + window.location.href = `${url}/oauth/logout`; } -} - -const loadUserSettings = (user: User | undefined, dispatcher: Dispatch) =>{ +}; +/** + * Loads the user settings for the given user and dispatches a `saveInitialSettings` action with the result. + * @param user The user for which to load the settings. + * @param dispatcher The dispatcher function to use for dispatching the `saveInitialSettings` action. + */ +const loadUserSettings = (user: User | undefined, dispatcher: Dispatch) => { - //fetch used, because state change for user login is not done when frameworks restRequest call is started (and is accordingly undefined -> /userdata call yields 401, unauthorized) and triggering an action from inside the handler / login event is impossible - //no timeout used, because it's bad practise to add a timeout to hopefully avoid a race condition - //hence, fetch used to simply use supplied user data for getting settings + // fetch used, because state change for user login is not done when frameworks restRequest call is started (and is accordingly undefined -> /userdata call yields 401, unauthorized) and triggering an action from inside the handler / login event is impossible + // no timeout used, because it's bad practice to add a timeout to hopefully avoid a race condition + // hence, fetch used to simply use supplied user data for getting settings - if(user && user.isValid){ + if (user && user.isValid) { - fetch("/userdata", { + fetch('/userdata', { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', - 'Authorization': `${user.tokenType} ${user.token}` - } + 'Authorization': `${user.tokenType} ${user.token}`, + }, }).then((res: Response)=>{ - if(res.status==200){ + if (res.status == 200) { return res.json(); - }else{ + } else { return null; } }).then((result:Settings)=>{ - dispatcher(saveInitialSettings(result)); - }) + dispatcher(saveInitialSettings(result)); + }); } -}
\ No newline at end of file +}; + +/** + * Dispatches an `UpdateUser` action with the given user and starts a user session if the user is defined. + * Also loads the user settings for the given user and dispatches a `saveInitialSettings` action with the result. + * Finally, saves the user token to local storage. + * @param user The user to be logged in. + * @param dispatcher The dispatcher function to use for dispatching the actions. + */ +export const loginUserAction = (user?: User) => (dispatcher: Dispatch) =>{ + + dispatcher(new UpdateUser(user)); + if (user) { + startUserSession(user); + loadUserSettings(user, dispatcher); + localStorage.setItem('userToken', user.toString()); + } +};
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/actions/settingsAction.ts b/sdnr/wt/odlux/framework/src/actions/settingsAction.ts index 092b31814..fa45f239c 100644 --- a/sdnr/wt/odlux/framework/src/actions/settingsAction.ts +++ b/sdnr/wt/odlux/framework/src/actions/settingsAction.ts @@ -19,7 +19,7 @@ import { Dispatch } from "../flux/store"; import { Action } from "../flux/action"; import { GeneralSettings, Settings, TableSettings, TableSettingsColumn } from "../models/settings"; -import { getUserdata, saveUserdata } from "../services/userdataService"; +import { getUserData, saveUserData } from "../services/userdataService"; import { startWebsocketSession, suspendWebsocketSession } from "../services/notificationService"; import { IApplicationStoreState } from "../store/applicationStore"; @@ -67,7 +67,7 @@ export const setGeneralSettingsAction = (value: boolean) => (dispatcher: Dispatc export const updateGeneralSettingsAction = (activateNotifications: boolean) => async (dispatcher: Dispatch) => { const value: GeneralSettings = { general: { areNotificationsEnabled: activateNotifications } }; - const result = await saveUserdata("/general", JSON.stringify(value.general)); + const result = await saveUserData("/general", JSON.stringify(value.general)); dispatcher(setGeneralSettingsAction(activateNotifications)); } @@ -86,14 +86,14 @@ export const updateTableSettings = (tableName: string, columns: TableSettingsCol // would only save latest entry //const json = JSON.stringify({ [tableName]: { columns: columns } }); - const result = await saveUserdata("/tables", json); + const result = await saveUserData("/tables", json); dispatcher(new SetTableSettings(tableName, columns)); } export const getGeneralSettingsAction = () => async (dispatcher: Dispatch) => { - const result = await getUserdata<GeneralSettings>(); + const result = await getUserData<GeneralSettings>(); if (result && result.general) { dispatcher(new SetGeneralSettingsAction(result.general.areNotificationsEnabled!)) diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx index d969286b7..bcc191a89 100644 --- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx +++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx @@ -164,7 +164,7 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di icon={faProjectDiagram} external />; - const linkFound = menuItems.find(obj => obj.key === "linkCalculation"); + const linkFound = menuItems.find(obj => obj.key === "microwave"); if (linkFound) { const index = menuItems.indexOf(linkFound); diff --git a/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts b/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts index 71b9e33d1..3a4891c98 100644 --- a/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts +++ b/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts @@ -23,7 +23,7 @@ import { AuthPolicy, User } from '../models/authentication'; import { onLogin, onLogout } from '../services/applicationApi'; import { startWebsocketSession, endWebsocketSession } from '../services/notificationService'; import { startUserSession, endUserSession } from '../services/userSessionService'; -import { getUserdata } from '../services/userdataService'; +import { getUserData } from '../services/userdataService'; export interface IAuthenticationState { user?: User; diff --git a/sdnr/wt/odlux/framework/src/middleware/navigation.ts b/sdnr/wt/odlux/framework/src/middleware/navigation.ts index 44035fec3..14ff09f77 100644 --- a/sdnr/wt/odlux/framework/src/middleware/navigation.ts +++ b/sdnr/wt/odlux/framework/src/middleware/navigation.ts @@ -16,60 +16,62 @@ * ============LICENSE_END========================================================================== */ import * as jwt from 'jsonwebtoken'; -import { Location, History, createHashHistory } from "history"; +import { History, createHashHistory } from 'history'; -import { User } from "../models/authentication"; +import { User } from '../models/authentication'; -import { LocationChanged, NavigateToApplication } from "../actions/navigationActions"; +import { LocationChanged, NavigateToApplication } from '../actions/navigationActions'; import { PushAction, ReplaceAction, GoAction, GoBackAction, GoForwardeAction } from '../actions/navigationActions'; -import { applicationManager } from "../services/applicationManager"; -import { loginUserAction, logoutUser } from "../actions/authentication"; +import { applicationManager } from '../services/applicationManager'; +import { loginUserAction, logoutUser } from '../actions/authentication'; -import { ApplicationStore } from "../store/applicationStore"; +import { ApplicationStore } from '../store/applicationStore'; import { Dispatch } from '../flux/store'; -const routerMiddlewareCreator = (history: History) => () => (next: Dispatch): Dispatch => (action) => { +export const history = createHashHistory(); +let applicationStore: ApplicationStore | null = null; + +const routerMiddlewareCreator = (historyParam: History) => () => (next: Dispatch): Dispatch => (action) => { if (action instanceof NavigateToApplication) { const application = applicationManager.applications && applicationManager.applications[action.applicationName]; if (application) { const href = `/${application.path || application.name}${action.href ? '/' + action.href : ''}`.replace(/\/{2,}/i, '/'); if (action.replace) { - history.replace(href, action.state); + historyParam.replace(href, action.state); } else { - history.push(href, action.state); + historyParam.push(href, action.state); } } } else if (action instanceof PushAction) { - history.push(action.href, action.state); + historyParam.push(action.href, action.state); } else if (action instanceof ReplaceAction) { - history.replace(action.href, action.state); + historyParam.replace(action.href, action.state); } else if (action instanceof GoAction) { - history.go(action.index); + historyParam.go(action.index); } else if (action instanceof GoBackAction) { - history.goBack(); + historyParam.goBack(); } else if (action instanceof GoForwardeAction) { - history.goForward(); + historyParam.goForward(); } else if (action instanceof LocationChanged) { // ensure user is logged in and token is valid - if (action.pathname.startsWith("/oauth") && (action.search.startsWith("?token="))){ - const ind = action.search.lastIndexOf("token="); - const tokenStr = ind > -1 ? action.search.substring(ind+6) : null; + if (action.pathname.startsWith('/oauth') && (action.search.startsWith('?token='))) { + const ind = action.search.lastIndexOf('token='); + const tokenStr = ind > -1 ? action.search.substring(ind + 6) : null; const token = tokenStr && jwt.decode(tokenStr); if (tokenStr && token) { // @ts-ignore - const user = new User({ username: token["name"], access_token: tokenStr, token_type: "Bearer", expires: token['exp'], issued: token['iat'] }) || undefined; + const user = new User({ username: token.name, access_token: tokenStr, token_type: 'Bearer', expires: token.exp, issued: token.iat }) || undefined; applicationStore?.dispatch(loginUserAction(user)); } - } if (!action.pathname.startsWith("/login") && applicationStore && (!applicationStore.state.framework.authenticationState.user || !applicationStore.state.framework.authenticationState.user.isValid)) { - history.replace(`/login?returnTo=${action.pathname}`); + } if (!action.pathname.startsWith('/login') && applicationStore && (!applicationStore.state.framework.authenticationState.user || !applicationStore.state.framework.authenticationState.user.isValid)) { + historyParam.replace(`/login?returnTo=${action.pathname}`); applicationStore.dispatch(logoutUser()); - }else if (action.pathname.startsWith("/login") && applicationStore && (applicationStore.state.framework.authenticationState.user && applicationStore.state.framework.authenticationState.user.isValid)) { - history.replace(`/`); - } - else { + } else if (action.pathname.startsWith('/login') && applicationStore && (applicationStore.state.framework.authenticationState.user && applicationStore.state.framework.authenticationState.user.isValid)) { + historyParam.replace('/'); + } else { return next(action); } } else { @@ -78,20 +80,17 @@ const routerMiddlewareCreator = (history: History) => () => (next: Dispatch): Di return action; }; -function startListener(history: History, store: ApplicationStore) { - store.dispatch(new LocationChanged(history.location.pathname, history.location.search, history.location.hash)); - history.listen((location: Location) => { +const startListener = (historyParam: History, store: ApplicationStore) => { + store.dispatch(new LocationChanged(historyParam.location.pathname, historyParam.location.search, historyParam.location.hash)); + historyParam.listen((location) => { store.dispatch(new LocationChanged(location.pathname, location.search, location.hash)); }); -} - -const history = createHashHistory(); -let applicationStore: ApplicationStore | null = null; +}; -export function startHistoryListener(store: ApplicationStore) { +export const startHistoryListener = (store: ApplicationStore) => { applicationStore = store; startListener(history, store); -} +}; export const routerMiddleware = routerMiddlewareCreator(history); export default routerMiddleware; diff --git a/sdnr/wt/odlux/framework/src/models/settings.ts b/sdnr/wt/odlux/framework/src/models/settings.ts index 11ba2f901..1752d6a52 100644 --- a/sdnr/wt/odlux/framework/src/models/settings.ts +++ b/sdnr/wt/odlux/framework/src/models/settings.ts @@ -17,35 +17,32 @@ */ export type TableSettingsColumn = { - property: string, - displayed: boolean -} + property: string; + displayed: boolean; +}; export type TableSettings = { - tables:{ - [key: string]: { - columns: TableSettingsColumn[] + tables:{ + [key: string]: { + columns: TableSettingsColumn[]; - //match prop names, hide them - //via property name! -> only those which are hidden! - //all others default false, oh yeah - //or maybe the other way around, gotta think about that - - } - } + //match prop names, hide them + //via property name! -> only those which are hidden! + //all others default false, oh yeah + //or maybe the other way around, gotta think about that - - -} + }; + }; +}; export type GeneralSettings = { - general:{ - areNotificationsEnabled: boolean | null - } + general:{ + areNotificationsEnabled: boolean | null; + }; }; -export type Settings= TableSettings & GeneralSettings; +export type Settings = TableSettings & GeneralSettings; export type SettingsComponentProps = { - onClose(): void + onClose(): void; };
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/services/applicationApi.ts b/sdnr/wt/odlux/framework/src/services/applicationApi.ts index 8246ee8fa..faa998450 100644 --- a/sdnr/wt/odlux/framework/src/services/applicationApi.ts +++ b/sdnr/wt/odlux/framework/src/services/applicationApi.ts @@ -18,7 +18,7 @@ import { Event } from '../common/event'; import { ApplicationStore } from '../store/applicationStore'; -import { AuthMessage, getBroadcastChannel, sendMessage } from './broadcastService'; +import { AuthMessage, sendMessage } from './broadcastService'; let resolveApplicationStoreInitialized: (store: ApplicationStore) => void; let applicationStore: ApplicationStore | null = null; @@ -26,32 +26,32 @@ const applicationStoreInitialized: Promise<ApplicationStore> = new Promise((reso const loginEvent = new Event(); const logoutEvent = new Event(); -let channel : BroadcastChannel | undefined; -const authChannelName = "odlux_auth"; + +const authChannelName = 'odlux_auth'; export const onLogin = () => { - const message : AuthMessage = {key: 'login', data: {}} + const message : AuthMessage = { key: 'login', data: {} }; sendMessage(message, authChannelName); loginEvent.invoke(); -} +}; export const onLogout = () => { - document.cookie = "JSESSIONID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; + document.cookie = 'JSESSIONID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; - const message : AuthMessage = {key: 'logout', data: {}} + const message : AuthMessage = { key: 'logout', data: {} }; sendMessage(message, authChannelName); logoutEvent.invoke(); -} +}; export const setApplicationStore = (store: ApplicationStore) => { if (!applicationStore && store) { applicationStore = store; resolveApplicationStoreInitialized(store); } -} +}; export const applicationApi = { get applicationStore(): ApplicationStore | null { @@ -68,7 +68,7 @@ export const applicationApi = { get logoutEvent() { return logoutEvent; - } + }, }; export default applicationApi;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/services/broadcastService.ts b/sdnr/wt/odlux/framework/src/services/broadcastService.ts index 40968e54f..202bf5563 100644 --- a/sdnr/wt/odlux/framework/src/services/broadcastService.ts +++ b/sdnr/wt/odlux/framework/src/services/broadcastService.ts @@ -16,11 +16,11 @@ * ============LICENSE_END========================================================================== */ -import { setGeneralSettingsAction } from "../actions/settingsAction"; -import { loginUserAction, logoutUser } from "../actions/authentication"; -import { ReplaceAction } from "../actions/navigationActions"; -import { User } from "../models/authentication"; -import { ApplicationStore } from "../store/applicationStore"; +import { setGeneralSettingsAction } from '../actions/settingsAction'; +import { loginUserAction, logoutUser } from '../actions/authentication'; +import { ReplaceAction } from '../actions/navigationActions'; +import { User } from '../models/authentication'; +import { ApplicationStore } from '../store/applicationStore'; type Broadcaster = { channel: BroadcastChannel; @@ -47,17 +47,9 @@ export const saveChannel = (channel: BroadcastChannel, channelName: string) => { channels.push({ channel: channel, key: channelName }); }; -export const startBroadcastChannel = (applicationStore: ApplicationStore) => { - store = applicationStore; - - //might decide to use one general broadcast channel with more keys in the future - createAuthBroadcastChannel(); - createSettingsBroadcastChannel(); -}; - const createSettingsBroadcastChannel = () => { - const name = "odlux_settings"; + const name = 'odlux_settings'; const bc: BroadcastChannel = new BroadcastChannel(name); channels.push({ channel: bc, key: name }); @@ -73,34 +65,41 @@ const createSettingsBroadcastChannel = () => { } } } - } + }; }; const createAuthBroadcastChannel = () => { - const name = "odlux_auth"; + const name = 'odlux_auth'; const bc: BroadcastChannel = new BroadcastChannel(name); channels.push({ channel: bc, key: name }); bc.onmessage = (eventMessage: MessageEvent<AuthMessage>) => { - console.log(eventMessage) + console.log(eventMessage); if (eventMessage.data.key === 'login') { if (!store?.state.framework.authenticationState.user) { - const initialToken = localStorage.getItem("userToken"); + const initialToken = localStorage.getItem('userToken'); if (initialToken) { store?.dispatch(loginUserAction(User.fromString(initialToken))); - store?.dispatch(new ReplaceAction("/")); + store?.dispatch(new ReplaceAction('/')); } } - } - else if (eventMessage.data.key === 'logout') { + } else if (eventMessage.data.key === 'logout') { if (store?.state.framework.authenticationState.user) { store?.dispatch(logoutUser()); - store?.dispatch(new ReplaceAction("/login")); + store?.dispatch(new ReplaceAction('/login')); } } - } + }; +}; + +export const startBroadcastChannel = (applicationStore: ApplicationStore) => { + store = applicationStore; + + // might decide to use one general broadcast channel with more keys in the future + createAuthBroadcastChannel(); + createSettingsBroadcastChannel(); }; export const getBroadcastChannel = (channelName: string) => { diff --git a/sdnr/wt/odlux/framework/src/services/index.ts b/sdnr/wt/odlux/framework/src/services/index.ts index 85f0708a6..2f64ba0ac 100644 --- a/sdnr/wt/odlux/framework/src/services/index.ts +++ b/sdnr/wt/odlux/framework/src/services/index.ts @@ -18,5 +18,5 @@ export { applicationManager } from './applicationManager'; export { subscribe, unsubscribe } from './notificationService'; export { requestRest } from './restService'; -export { saveUserdata, getUserdata } from './userdataService'; +export { saveUserData as saveUserdata, getUserData as getUserdata } from './userdataService'; diff --git a/sdnr/wt/odlux/framework/src/services/restService.ts b/sdnr/wt/odlux/framework/src/services/restService.ts index a296c52a4..0be3dca07 100644 --- a/sdnr/wt/odlux/framework/src/services/restService.ts +++ b/sdnr/wt/odlux/framework/src/services/restService.ts @@ -68,41 +68,30 @@ export const getAccessPolicyByUrl = (url: string) => { }; -/** Sends a rest request to the given path. - * @returns The data, or null it there was any error - */ -export async function requestRest<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<TData | null | undefined> { - const res = await requestRestExt<TData>(path, init, authenticate, isResource); - if (res && res.status >= 200 && res.status < 300) { - return res.data; - } - return null; -} - /** Sends a rest request to the given path and reports the server state. * @returns An object with the server state, a message and the data or undefined in case of a json parse error. */ -export async function requestRestExt<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number; message?: string; data: TData | null | undefined }> { +export async function requestRestExt<TData>(path: string = '', initParam: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number; message?: string; data: TData | null | undefined }> { const result: { status: number; message?: string; data: TData | null } = { status: -1, data: null, }; const isAbsUrl = absUrlPattern.test(path); const uri = isAbsUrl ? path : isResource ? path.replace(/\/{2,}/i, '/') : (baseUri) + ('/' + path).replace(/\/{2,}/i, '/'); - init = { + const init = { 'method': 'GET', - ...init, + ...initParam, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', - ...init.headers, - }, + ...initParam.headers, + } as HeadersInit, }; if (!isAbsUrl && authenticate && storeService.applicationStore) { const { state: { framework: { authenticationState: { user } } } } = storeService.applicationStore; // do not request if the user is not valid - if (!user || !user.isValid) { + if (!user || !user.isValid || !user.token || !user.tokenType) { return { ...result, message: 'User is not valid or not logged in.', @@ -116,16 +105,31 @@ export async function requestRestExt<TData>(path: string = '', init: RequestInit } const fetchResult = await fetch(uri, init); - - if (fetchResult.status === 403) { - storeService.applicationStore && storeService.applicationStore.dispatch(new AddErrorInfoAction({ title: 'Forbidden', message:'Status: [403], access denied.' })); + if (fetchResult.status === 309) { + const redirectUrl = fetchResult.headers.get('Location'); + if (! redirectUrl) { + throw new Error('Status code 309 requires header "Location"'); + } + localStorage.removeItem('userToken'); + window.location.href = redirectUrl; + return { + ...result, + status: fetchResult.status, + message: 'Redirecting to new URL.', + }; + } else if (fetchResult.status === 403) { + if (storeService.applicationStore) { + storeService.applicationStore.dispatch(new AddErrorInfoAction({ title: 'Forbidden', message:'Status: [403], access denied.' })); + } return { ...result, status: 403, message: 'Forbidden.', }; } else if (fetchResult.status === 401) { - storeService.applicationStore && storeService.applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${storeService.applicationStore.state.framework.navigationState.pathname}`)); + if (storeService.applicationStore) { + storeService.applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${storeService.applicationStore.state.framework.navigationState.pathname}`)); + } return { ...result, status: 401, @@ -150,4 +154,15 @@ export async function requestRestExt<TData>(path: string = '', init: RequestInit data: undefined, }; } +} + +/** Sends a rest request to the given path. + * @returns The data, or null it there was any error + */ +export async function requestRest<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<TData | null | undefined> { + const res = await requestRestExt<TData>(path, init, authenticate, isResource); + if (res && res.status >= 200 && res.status < 300) { + return res.data; + } + return null; }
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/services/userdataService.ts b/sdnr/wt/odlux/framework/src/services/userdataService.ts index 5c9b576c3..53de8e1c3 100644 --- a/sdnr/wt/odlux/framework/src/services/userdataService.ts +++ b/sdnr/wt/odlux/framework/src/services/userdataService.ts @@ -16,26 +16,13 @@ * ============LICENSE_END========================================================================== */ -import { requestRest } from "./restService"; +import { requestRest } from './restService'; +const settingsPath = '/userdata'; - const settingsPath ="/userdata"; +export const getUserData = <TData>(partialPath?: string) => requestRest<TData>(partialPath ? settingsPath + partialPath : settingsPath, { method: 'GET' }); +export const saveUserData = <TData>(partialPath: string, data: string) => requestRest<TData>(settingsPath + partialPath, { method: 'PUT', body: data }); - export function getUserdata<TData>(partialPath?: string){ - let path = settingsPath; - if(partialPath){ - path+=partialPath - } - - const result = requestRest<TData>(path, {method: "GET"}) - return result; - } - - export function saveUserdata<TData>(partialPath: string, data: string){ - - const result = requestRest<TData>(settingsPath+partialPath, {method: "PUT", body: data}) - return result; - } diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx index 937e74f33..9fe48ca38 100644 --- a/sdnr/wt/odlux/framework/src/views/about.tsx +++ b/sdnr/wt/odlux/framework/src/views/about.tsx @@ -34,11 +34,9 @@ type OdluxVersion= {version:string,build:string, framework: string, faultApp: string, helpApp: string, inventoryApp: string, - linkCalculationApp: string, maintenanceApp: string, mediatorApp: string, - networkMapApp: string, - permanceHistoryApp: string + permanceHistoryApp: string, }}; type TopologyVersion = {version: string, buildTimestamp: string}; @@ -70,8 +68,6 @@ const AboutComponent: FC = (props) => { `| InventoryApp | ${data.applications.inventoryApp}|\n `+ `| EventLogApp | ${data.applications.eventLogApp}|\n `+ `| MediatorApp | ${data.applications.mediatorApp}|\n `+ - `| NetworkMapApp | ${data.applications.networkMapApp}|\n `+ - `| LinkCalculatorApp | ${data.applications.linkCalculationApp}|\n `+ `| HelpApp | ${data.applications.helpApp}|\n `; } diff --git a/sdnr/wt/odlux/framework/src/views/frame.tsx b/sdnr/wt/odlux/framework/src/views/frame.tsx index 4a93cf0ae..2c9f8c033 100644 --- a/sdnr/wt/odlux/framework/src/views/frame.tsx +++ b/sdnr/wt/odlux/framework/src/views/frame.tsx @@ -16,7 +16,7 @@ * ============LICENSE_END========================================================================== */ import React, { FC, memo } from 'react'; -import { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; +import { Router, Route, Redirect, Switch } from 'react-router-dom'; import { Theme } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; @@ -38,11 +38,14 @@ import UserSettings from '../views/settings'; import applicationService from '../services/applicationManager'; +import { history } from '../middleware/navigation'; + const aboutIcon = require('../assets/icons/About.svg'); const homeIcon = require('../assets/icons/Home.svg'); const loginIcon = require('../assets/icons/User.svg'); const settingsIcon = require('../assets/icons/Tools.svg'); + const styles = makeStyles((theme: Theme) => { return { @@ -73,7 +76,7 @@ const FrameComponent: FC = memo(() => { return ( <ConfirmProvider> <SnackbarProvider maxSnack={3}> - <Router> + <Router history={history as any} > <div className={classes.root}> <SnackDisplay /> <ErrorDisplay /> diff --git a/sdnr/wt/odlux/framework/src2/main/resources/version.json b/sdnr/wt/odlux/framework/src2/main/resources/version.json index 1d9af9029..f9e974672 100644 --- a/sdnr/wt/odlux/framework/src2/main/resources/version.json +++ b/sdnr/wt/odlux/framework/src2/main/resources/version.json @@ -9,10 +9,8 @@ "faultApp":"##odlux.apps.faultApp.buildno##", "helpApp":"##odlux.apps.helpApp.buildno##", "inventoryApp":"##odlux.apps.inventoryApp.buildno##", - "linkCalculationApp":"##odlux.apps.linkCalculationApp.buildno##", "maintenanceApp":"##odlux.apps.maintenanceApp.buildno##", "mediatorApp":"##odlux.apps.mediatorApp.buildno##", - "networkMapApp":"##odlux.apps.networkMapApp.buildno##", "permanceHistoryApp":"##odlux.apps.permanceHistoryApp.buildno##" } |