aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt-odlux/odlux/framework/src/services
diff options
context:
space:
mode:
authorRavi Pendurty <ravi.pendurty@highstreet-technologies.com>2023-12-07 22:45:28 +0530
committerRavi Pendurty <ravi.pendurty@highstreet-technologies.com>2023-12-07 22:46:39 +0530
commitdfd91573b7567e1dab482f17111ab8f809553d99 (patch)
tree8368580d1b1add9cfef5e8354ccf1080f27109b0 /sdnr/wt-odlux/odlux/framework/src/services
parentbf8d701f85d02a140a1290d288adc7f437c1cc90 (diff)
Create wt-odlux directory
Include odlux apps, helpserver and readthedocs Issue-ID: CCSDK-3970 Change-Id: I1aee1327e7da12e8f658185b9a985a5204ad6065 Signed-off-by: Ravi Pendurty <ravi.pendurty@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt-odlux/odlux/framework/src/services')
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts74
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts53
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts96
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts115
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/index.ts22
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts220
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts93
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/restService.ts168
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts22
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/storeService.ts11
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts80
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts28
12 files changed, 982 insertions, 0 deletions
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts b/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts
new file mode 100644
index 000000000..faa998450
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Event } from '../common/event';
+import { ApplicationStore } from '../store/applicationStore';
+import { AuthMessage, sendMessage } from './broadcastService';
+
+let resolveApplicationStoreInitialized: (store: ApplicationStore) => void;
+let applicationStore: ApplicationStore | null = null;
+const applicationStoreInitialized: Promise<ApplicationStore> = new Promise((resolve) => resolveApplicationStoreInitialized = resolve);
+
+const loginEvent = new Event();
+const logoutEvent = new Event();
+
+const authChannelName = 'odlux_auth';
+
+export const onLogin = () => {
+
+ 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=/;';
+
+ 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 {
+ return applicationStore;
+ },
+
+ get applicationStoreInitialized(): Promise<ApplicationStore> {
+ return applicationStoreInitialized;
+ },
+
+ get loginEvent() {
+ return loginEvent;
+ },
+
+ get logoutEvent() {
+ return logoutEvent;
+ },
+};
+
+export default applicationApi; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts b/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts
new file mode 100644
index 000000000..bd620a020
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationInfo } from '../models/applicationInfo';
+import { Event } from '../common/event';
+
+import { applicationApi } from './applicationApi';
+
+/** Represents registry to manage all applications. */
+class ApplicationManager {
+
+ /** Stores all registered applications. */
+ private _applications: { [key: string]: ApplicationInfo };
+
+ /** Initializes a new instance of this class. */
+ constructor() {
+ this._applications = {};
+ this.changed = new Event<void>();
+ }
+
+ /** The changed event will fire if the registration has changed. */
+ public changed: Event<void>;
+
+ /** Registers a new application. */
+ public registerApplication(applicationInfo: ApplicationInfo) {
+ this._applications[applicationInfo.name] = applicationInfo;
+ this.changed.invoke();
+ return applicationApi;
+ }
+
+ /** Gets all registered applications. */
+ public get applications() {
+ return this._applications;
+ }
+}
+
+/** A singleton instance of the application manager. */
+export const applicationManager = new ApplicationManager();
+export default applicationManager; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts b/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts
new file mode 100644
index 000000000..b9c1a5a94
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts
@@ -0,0 +1,96 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { AuthPolicy, AuthToken } from "../models/authentication";
+import { ExternalLoginProvider } from "../models/externalLoginProvider";
+
+import { requestRest, formEncode, requestRestExt } from "./restService";
+
+type AuthTokenResponse = {
+ access_token: string;
+ token_type: string;
+ expires_at: number;
+ issued_at: number;
+}
+
+class AuthenticationService {
+ public async getAvaliableExteralProvider() {
+ const result = await requestRest<ExternalLoginProvider[]>(`oauth/providers`, {
+ method: "GET",
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ }, false);
+ return result;
+ }
+
+ public async authenticateUserOAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
+ const result = await requestRest<AuthTokenResponse>(`oauth/login`, {
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ body: formEncode({
+ grant_type: "password",
+ username: email,
+ password: password,
+ scope: scope
+ })
+ }, false);
+
+
+ return result && {
+ username: email,
+ access_token: result.access_token,
+ token_type: result.token_type,
+ expires: result.expires_at,
+ issued: result.issued_at
+ } || null;
+ }
+
+ public async authenticateUserBasicAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
+ const result = await requestRest<string>(`rests/data/network-topology:network-topology/topology=topology-netconf?fields=node(node-id)`, {
+ method: "GET",
+ headers: {
+ 'Authorization': "Basic " + btoa(email + ":" + password)
+ },
+ }, false);
+
+ if (result) {
+ return {
+ username: email,
+ access_token: btoa(email + ":" + password),
+ token_type: "Basic",
+ expires: (new Date()).valueOf() / 1000 + 86400, // 1 day
+ issued: (new Date()).valueOf() / 1000
+ }
+ }
+ return null;
+ }
+
+ public async getAccessPolicies(){
+ return await requestRest<AuthPolicy[]>(`oauth/policies`, { method: "GET" }, true);
+ }
+
+ public async getServerReadyState(){
+ const result = await requestRestExt(`/ready`, { method: "GET" }, false);
+ return result.status == (200 || 304) ? true : false;
+ }
+}
+
+export const authenticationService = new AuthenticationService();
+export default authenticationService; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts b/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts
new file mode 100644
index 000000000..202bf5563
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts
@@ -0,0 +1,115 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============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';
+
+type Broadcaster = {
+ channel: BroadcastChannel;
+ key: String;
+};
+
+type AuthTypes = 'login' | 'logout';
+export type AuthMessage = {
+ key: AuthTypes;
+ data: any;
+};
+
+type SettingsType = 'general';
+export type SettingsMessage = {
+ key: SettingsType;
+ enableNotifications: boolean;
+ user: string;
+};
+
+const channels: Broadcaster[] = [];
+let store: ApplicationStore | null = null;
+
+export const saveChannel = (channel: BroadcastChannel, channelName: string) => {
+ channels.push({ channel: channel, key: channelName });
+};
+
+const createSettingsBroadcastChannel = () => {
+
+ const name = 'odlux_settings';
+ const bc: BroadcastChannel = new BroadcastChannel(name);
+ channels.push({ channel: bc, key: name });
+
+ bc.onmessage = (eventMessage: MessageEvent<SettingsMessage>) => {
+ console.log(eventMessage);
+
+ if (eventMessage.data.key === 'general') {
+
+ if (store?.state.framework.authenticationState.user) {
+ const data = eventMessage.data;
+ if (store.state.framework.authenticationState.user.user === data.user) {
+ store?.dispatch(setGeneralSettingsAction(data.enableNotifications));
+ }
+ }
+ }
+ };
+};
+
+const createAuthBroadcastChannel = () => {
+ const name = 'odlux_auth';
+ const bc: BroadcastChannel = new BroadcastChannel(name);
+ channels.push({ channel: bc, key: name });
+
+ bc.onmessage = (eventMessage: MessageEvent<AuthMessage>) => {
+ console.log(eventMessage);
+
+ if (eventMessage.data.key === 'login') {
+ if (!store?.state.framework.authenticationState.user) {
+ const initialToken = localStorage.getItem('userToken');
+ if (initialToken) {
+ store?.dispatch(loginUserAction(User.fromString(initialToken)));
+ store?.dispatch(new ReplaceAction('/'));
+ }
+ }
+ } else if (eventMessage.data.key === 'logout') {
+
+ if (store?.state.framework.authenticationState.user) {
+ store?.dispatch(logoutUser());
+ 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) => {
+ const foundChannel = channels.find(s => s.key === channelName);
+ return foundChannel?.channel;
+};
+
+export const sendMessage = (data: any, channel: string) => {
+ const foundChannel = channels.find(s => s.key === channel);
+ if (foundChannel) {
+ foundChannel.channel.postMessage(data);
+ }
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/index.ts b/sdnr/wt-odlux/odlux/framework/src/services/index.ts
new file mode 100644
index 000000000..2f64ba0ac
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/index.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { applicationManager } from './applicationManager';
+export { subscribe, unsubscribe } from './notificationService';
+export { requestRest } from './restService';
+export { saveUserData as saveUserdata, getUserData as getUserdata } from './userdataService';
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts b/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts
new file mode 100644
index 000000000..b2880b9de
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts
@@ -0,0 +1,220 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationStore } from '../store/applicationStore';
+import { SetWebsocketAction } from '../actions/websocketAction';
+
+const socketUrl = [location.protocol === 'https:' ? 'wss://' : 'ws://', location.hostname, ':', location.port, '/websocket'].join('');
+const subscriptions: { [scope: string]: SubscriptionCallback[] } = {};
+let socketReady: Promise<WebSocket>;
+let wasWebsocketConnectionEstablished: undefined | boolean;
+let applicationStore: ApplicationStore | null;
+
+let areWebsocketsStoppedViaSettings = false;
+
+
+export interface IFormatedMessage {
+ "event-time": string,
+ "data": {
+ "counter": number,
+ "attribute-name": string,
+ "time-stamp": string,
+ "object-id-ref": string,
+ "new-value": string
+ },
+ "node-id": string,
+ "type": {
+ "namespace": string,
+ "revision": string,
+ "type": string
+ }
+}
+
+export type SubscriptionCallback<TMessage extends IFormatedMessage = IFormatedMessage> = (msg: TMessage) => void;
+
+function setCurrentSubscriptions(notificationSocket: WebSocket) {
+ const scopesToSubscribe = Object.keys(subscriptions);
+ if (notificationSocket.readyState === notificationSocket.OPEN) {
+ const data = {
+ 'data': 'scopes',
+ 'scopes':[{
+ "schema":{
+ "namespace":"urn:opendaylight:params:xml:ns:yang:devicemanager",
+ "revision":"*",
+ "notification": scopesToSubscribe
+ }
+ }]
+ };
+ notificationSocket.send(JSON.stringify(data));
+ return true;
+ };
+ return false;
+}
+
+function addScope<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>) {
+ const scopes = scope instanceof Array ? scope : [scope];
+
+ // send all new scopes to subscribe
+ const newScopesToSubscribe: string[] = scopes.reduce((acc: string[], cur: string) => {
+ const currentCallbacks = subscriptions[cur];
+ if (currentCallbacks) {
+ if (!currentCallbacks.some(c => c === callback)) {
+ currentCallbacks.push(callback);
+ }
+ } else {
+ subscriptions[cur] = [callback];
+ acc.push(cur);
+ }
+ return acc;
+ }, []);
+
+ if (newScopesToSubscribe.length === 0) {
+ return true;
+ }
+ return false;
+}
+
+function removeScope<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>) {
+ const scopes = scope instanceof Array ? scope : [scope];
+ scopes.forEach(s => {
+ const callbacks = subscriptions[s];
+ const index = callbacks && callbacks.indexOf(callback);
+ if (index > -1) {
+ callbacks.splice(index, 1);
+ }
+ if (callbacks.length === 0) {
+ subscriptions[s] === undefined;
+ }
+ });
+}
+
+export function subscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): Promise<boolean> {
+ addScope(scope, callback)
+ return socketReady && socketReady.then((notificationSocket) => {
+ // send a subscription to all active scopes
+ return setCurrentSubscriptions(notificationSocket);
+ }) || true;
+}
+
+export function unsubscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): Promise<boolean> {
+ removeScope(scope, callback);
+ return socketReady && socketReady.then((notificationSocket) => {
+ // send a subscription to all active scopes
+ return setCurrentSubscriptions(notificationSocket);
+ }) || true;
+}
+
+export const startNotificationService = (store: ApplicationStore) => {
+ applicationStore = store;
+}
+
+const connect = (): Promise<WebSocket> => {
+ return new Promise((resolve, reject) => {
+ const notificationSocket = new WebSocket(socketUrl);
+
+ notificationSocket.onmessage = (event: MessageEvent<string>) => {
+ // process received event
+
+ if (event.data && typeof event.data === "string" ) {
+ const msg = JSON.parse(event.data) as IFormatedMessage;
+ const callbacks = msg?.type?.type && subscriptions[msg.type.type];
+ if (callbacks) {
+ callbacks.forEach(cb => {
+ // ensure all callbacks will be called
+ try {
+ return cb(msg);
+ } catch (reason) {
+ console.error(reason);
+ }
+ });
+ }
+ }
+
+ };
+
+ notificationSocket.onerror = function (error) {
+ console.log("Socket error:");
+ console.log(error);
+ reject("Socket error: " + error);
+ if (applicationStore) {
+ applicationStore.dispatch(new SetWebsocketAction(false));
+ }
+ };
+
+ notificationSocket.onopen = function (event) {
+ if (applicationStore) {
+ applicationStore.dispatch(new SetWebsocketAction(true));
+ }
+ console.log("Socket connection opened.");
+ resolve(notificationSocket);
+
+ // send a subscription to all active scopes
+ setCurrentSubscriptions(notificationSocket);
+ };
+
+ notificationSocket.onclose = function (event) {
+ console.log("socket connection closed");
+ dispatchSocketClose();
+
+ const isUserLoggedIn = applicationStore?.state.framework.authenticationState.user && applicationStore?.state.framework.authenticationState.user?.isValid;
+
+ if (isUserLoggedIn && !areWebsocketsStoppedViaSettings) {
+ socketReady = connect();
+ }
+ };
+ });
+}
+
+
+export const startWebsocketSession = () => {
+ socketReady = connect();
+ areWebsocketsStoppedViaSettings = false;
+}
+
+export const suspendWebsocketSession = () =>{
+ areWebsocketsStoppedViaSettings = true;
+ closeSocket();
+}
+
+export const endWebsocketSession = () => {
+ closeSocket();
+}
+
+const closeSocket = () =>{
+
+ if (socketReady) {
+ socketReady.then(websocket => {
+ websocket.close();
+ });
+ }else{
+ dispatchSocketClose();
+ }
+}
+
+const dispatchSocketClose = () =>{
+ const isUserLoggedIn = applicationStore?.state.framework.authenticationState.user && applicationStore?.state.framework.authenticationState.user?.isValid;
+
+ if(isUserLoggedIn){
+ applicationStore?.dispatch(new SetWebsocketAction(false));
+ }else{
+ applicationStore?.dispatch(new SetWebsocketAction(null));
+ }
+}
+
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts b/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts
new file mode 100644
index 000000000..5ed4d7b6e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts
@@ -0,0 +1,93 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as $ from 'jquery';
+import { Action, IActionHandler } from '../flux/action';
+import { MiddlewareArg } from '../flux/middleware';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { AddErrorInfoAction, ErrorInfo } from '../actions/errorActions';
+import { PlainObject, AjaxParameter } from 'models/restService';
+
+export const absoluteUri = /^(https?:\/\/|blob:)/i;
+export const baseUrl = `${ window.location.origin }${ window.location.pathname }`;
+
+class RestBaseAction extends Action { }
+
+export const createRestApiAccessor = <TResult extends PlainObject>(urlOrPath: string, initialValue: TResult) => {
+ const isLocalRequest = !absoluteUri.test(urlOrPath);
+ const uri = isLocalRequest ? `${ baseUrl }/${ urlOrPath }`.replace(/\/{2,}/, '/') : urlOrPath ;
+
+ class RestRequestAction extends RestBaseAction { constructor(public settings?: AjaxParameter) { super(); } }
+
+ class RestResponseAction extends RestBaseAction { constructor(public result: TResult) { super(); } }
+
+ class RestErrorAction extends RestBaseAction { constructor(public error?: Error | string) { super(); } }
+
+ type RestAction = RestRequestAction | RestResponseAction | RestErrorAction;
+
+ /** Represents our middleware to handle rest backend requests */
+ const restMiddleware = (api: MiddlewareArg<IApplicationStoreState>) =>
+ (next: Dispatch) => (action: RestAction): RestAction => {
+
+ // pass all actions through by default
+ next(action);
+ // handle the RestRequestAction
+ if (action instanceof RestRequestAction) {
+ const state = api.getState();
+ const authHeader = isLocalRequest && state && state.framework.authenticationState.user && state.framework.authenticationState.user.token
+ ? { "Authentication": "Bearer " + state.framework.authenticationState.user.token } : { };
+ $.ajax({
+ url: uri,
+ method: (action.settings && action.settings.method) || "GET",
+ headers: { ...authHeader, ...(action.settings && action.settings.headers ? action.settings.headers : { }) },
+ }).then((data: TResult) => {
+ next(new RestResponseAction(data));
+ }).catch((err: any) => {
+ next(new RestErrorAction());
+ next(new AddErrorInfoAction((err instanceof Error) ? { error: err } : { message: err.toString() }));
+ });
+ }
+ // allways return action
+ return action;
+ };
+
+ /** Represents our action handler to handle our actions */
+ const restActionHandler: IActionHandler<TResult> = (state = initialValue, action) => {
+ if (action instanceof RestRequestAction) {
+ return {
+ ...(state as any),
+ busy: true
+ };
+ } else if (action instanceof RestResponseAction) {
+ return action.result;
+ } else if (action instanceof RestErrorAction) {
+ return initialValue;
+ }
+ return state;
+ };
+
+ return {
+ requestAction: RestRequestAction,
+ actionHandler: restActionHandler,
+ middleware: restMiddleware,
+ };
+}
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/restService.ts b/sdnr/wt-odlux/odlux/framework/src/services/restService.ts
new file mode 100644
index 000000000..0be3dca07
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/restService.ts
@@ -0,0 +1,168 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ReplaceAction } from '../actions/navigationActions';
+import { AddErrorInfoAction } from '../actions/errorActions';
+
+import { storeService } from './storeService';
+
+const baseUri = `${ window.location.origin }`;
+const absUrlPattern = /^https?:\/\//;
+
+export const formEncode = (params: { [key: string]: string | number }) => Object.keys(params).map((key) => {
+ return encodeURIComponent(key) + '=' + encodeURIComponent(params[key].toString());
+}).join('&');
+
+const wildcardToRegexp = (pattern: string) => {
+ return new RegExp('^' + pattern.split(/\*\*/).map((p) => p.split(/\*+/).map((i) => i.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')).join('^[/]')).join('.*') + '$');
+};
+
+export const getAccessPolicyByUrl = (url: string) => {
+ const result = {
+ GET : false,
+ POST: false,
+ PUT: false,
+ PATCH: false,
+ DELETE: false,
+ };
+
+ if (!storeService.applicationStore) return result;
+
+ const { state: { framework: { applicationState: { enablePolicy }, authenticationState: { policies } } } } = storeService.applicationStore!;
+
+ result.GET = true;
+ result.POST = true;
+ result.PUT = true;
+ result.PATCH = true;
+ result.DELETE = true;
+
+ if (!enablePolicy || !policies || policies.length === 0) return result;
+
+ policies.forEach(p => {
+ const re = wildcardToRegexp(p.path);
+ if (re.test(url)) {
+ result.GET = p.methods.get != null ? p.methods.get : result.GET ;
+ result.POST = p.methods.post != null ? p.methods.post : result.POST ;
+ result.PUT = p.methods.put != null ? p.methods.put : result.PUT ;
+ result.PATCH = p.methods.patch != null ? p.methods.patch : result.PATCH ;
+ result.DELETE = p.methods.delete != null ? p.methods.delete : result.DELETE ;
+ }
+ });
+
+ return result;
+
+};
+
+/** 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 = '', 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, '/');
+ const init = {
+ 'method': 'GET',
+ ...initParam,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ ...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 || !user.token || !user.tokenType) {
+ return {
+ ...result,
+ message: 'User is not valid or not logged in.',
+ };
+ }
+ (init.headers = {
+ ...init.headers,
+ 'Authorization': `${user.tokenType} ${user.token}`,
+ //'Authorization': 'Basic YWRtaW46YWRtaW4='
+ });
+ }
+
+ const fetchResult = await fetch(uri, init);
+ 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) {
+ if (storeService.applicationStore) {
+ storeService.applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${storeService.applicationStore.state.framework.navigationState.pathname}`));
+ }
+ return {
+ ...result,
+ status: 401,
+ message: 'Authentication requested by server.',
+ };
+ }
+ const contentType = fetchResult.headers.get('Content-Type') || fetchResult.headers.get('content-type');
+ const isJson = contentType && (contentType.toLowerCase().startsWith('application/json') || contentType.toLowerCase().startsWith('application/yang-data+json'));
+ try {
+ const data = (isJson ? await fetchResult.json() : await fetchResult.text()) as TData;
+ return {
+ ...result,
+ status: fetchResult.status,
+ message: fetchResult.statusText,
+ data: data,
+ };
+ } catch (error) {
+ return {
+ ...result,
+ status: fetchResult.status,
+ message: error && error.message || String(error),
+ 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/odlux/framework/src/services/snackbarService.ts b/sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts
new file mode 100644
index 000000000..50e279c67
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { OptionsObject } from "notistack";
+
+export const snackbarService = {
+ enqueueSnackbar: (message: string, options?: OptionsObject) =>{ }
+} \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts b/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts
new file mode 100644
index 000000000..cbb5987de
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts
@@ -0,0 +1,11 @@
+import { ApplicationStore } from "../store/applicationStore";
+
+let applicationStore: ApplicationStore | null = null;
+
+export const startSoreService = (store: ApplicationStore) => {
+ applicationStore = store;
+};
+
+export const storeService = {
+ get applicationStore() { return applicationStore; },
+ }; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts b/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts
new file mode 100644
index 000000000..8d899c4d6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ApplicationStore } from "../store/applicationStore";
+import { logoutUser } from "../actions/authentication";
+import { ReplaceAction } from "../actions/navigationActions";
+import { AuthMessage, getBroadcastChannel } from "./broadcastService";
+import { User } from "../models/authentication";
+
+let currentUser: User | null;
+let applicationStore: ApplicationStore | null = null;
+let timer : null | ReturnType<typeof setTimeout> = null;
+
+export const startUserSessionService = (store: ApplicationStore) =>{
+ applicationStore=store;
+}
+
+export const startUserSession = (user: User) => {
+ console.log("user session started...")
+
+ const currentTime = new Date();
+ //get time differnce between login time and now (eg after user refreshes page)
+ const timeDiffernce =(currentTime.valueOf()/1000 - user.loginAt);
+
+ currentUser = user;
+
+ if (process.env.NODE_ENV === "development") {
+ //console.warn("logout timer not started in development mode");
+
+ const expiresIn = (user.logoutAt - user.loginAt) - timeDiffernce;
+ console.log("user should be logged out in: "+expiresIn/60 +"minutes")
+ createForceLogoutInterval(expiresIn);
+ } else {
+ const expiresIn = (user.logoutAt - user.loginAt) - timeDiffernce;
+ console.log("user should be logged out in: "+expiresIn/60 +"minutes")
+ createForceLogoutInterval(expiresIn);
+ }
+};
+
+const createForceLogoutInterval = (intervalInSec: number) => {
+ console.log("logout timer running...");
+
+ if(timer!==null){
+ console.error("an old session was available");
+ clearTimeout(timer);
+ }
+
+ timer = setTimeout(function () {
+ if (currentUser && applicationStore) {
+
+ applicationStore.dispatch(logoutUser());
+ applicationStore.dispatch(new ReplaceAction("/login"));
+
+ }
+
+ }, intervalInSec * 1000)
+}
+
+export const endUserSession = ()=>{
+
+ if(timer!==null){
+ clearTimeout(timer);
+ timer=null;
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts b/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts
new file mode 100644
index 000000000..53de8e1c3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { requestRest } from './restService';
+
+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 });
+
+
+