From df86ace4727334261f014d2321653ee46129b768 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Mon, 16 Dec 2024 12:01:57 +0100
Subject: [PATCH 1/2] [Requests] added error toasts display [Header] Removed
 useless imports

---
 src/actions/user.js                    | 16 ++++++------
 src/components/Header/Header.js        |  2 +-
 src/context/InSylvaGatekeeperClient.js |  2 +-
 src/pages/requests/Requests.js         | 34 ++++++++++++++++++--------
 4 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/src/actions/user.js b/src/actions/user.js
index fb7f9d4..180a086 100644
--- a/src/actions/user.js
+++ b/src/actions/user.js
@@ -148,25 +148,25 @@ export async function fetchPendingRequests(store, request = igClient) {
   }
 }
 
-export async function processUserRequest(store, requestId, request = igClient) {
+export const processUserRequest = async (store, requestId) => {
   store.setState({ isLoading: true });
-  request.token = sessionStorage.getItem('access_token');
+  igClient.token = sessionStorage.getItem('access_token');
   try {
-    await request.processUserRequest(requestId);
+    return await igClient.processUserRequest(requestId);
   } catch (error) {
     console.error(error);
   }
-}
+};
 
-export async function deleteUserRequest(store, requestId, request = igClient) {
+export const deleteUserRequest = async (store, requestId) => {
   store.setState({ isLoading: true });
-  request.token = sessionStorage.getItem('access_token');
+  igClient.token = sessionStorage.getItem('access_token');
   try {
-    await request.deleteUserRequest(requestId);
+    return await igClient.deleteUserRequest(requestId);
   } catch (error) {
     console.error(error);
   }
-}
+};
 
 export const createRole = async (store, name, description, request = igClient) => {
   try {
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
index 3064767..a534bad 100644
--- a/src/components/Header/Header.js
+++ b/src/components/Header/Header.js
@@ -1,5 +1,5 @@
 import React, { useState, useEffect, useCallback } from 'react';
-import { AppBar, Toolbar, IconButton, Menu, MenuItem } from '@material-ui/core';
+import { AppBar, Toolbar, IconButton, Menu } from '@material-ui/core';
 import {
   Menu as MenuIcon,
   Person as AccountIcon,
diff --git a/src/context/InSylvaGatekeeperClient.js b/src/context/InSylvaGatekeeperClient.js
index d1b8568..f976cd7 100644
--- a/src/context/InSylvaGatekeeperClient.js
+++ b/src/context/InSylvaGatekeeperClient.js
@@ -80,7 +80,7 @@ class InSylvaGatekeeperClient {
 
   async deleteUserRequest(id) {
     const path = `/user/delete-request`;
-    await this.post('DELETE', `${path}`, {
+    return await this.post('DELETE', `${path}`, {
       id,
     });
   }
diff --git a/src/pages/requests/Requests.js b/src/pages/requests/Requests.js
index 97bec19..04d3fcd 100644
--- a/src/pages/requests/Requests.js
+++ b/src/pages/requests/Requests.js
@@ -65,25 +65,39 @@ const Requests = () => {
   }, [loadRequests, loadPendingRequests]);
 
   const onDeleteRequest = async (request) => {
-    if (request) {
-      await globalActions.user.deleteUserRequest(request.id);
-      setOpen(true);
+    if (!request) {
+      return;
+    }
+    const result = await globalActions.user.deleteUserRequest(request.id);
+    if (result && !result.error) {
       setAlertMessage('Request has been deleted.');
       setSeverity('success');
-      await loadRequests();
-      await loadPendingRequests();
+      setOpen(true);
+    } else {
+      setAlertMessage(`Error: ${result.error}`);
+      setSeverity('error');
+      setOpen(true);
     }
+    await loadRequests();
+    await loadPendingRequests();
   };
 
   const onProcessRequest = async (request) => {
-    if (request) {
-      await globalActions.user.processUserRequest(request.id);
-      setOpen(true);
+    if (!request) {
+      return;
+    }
+    const result = await globalActions.user.processUserRequest(request.id);
+    if (result && !result.error) {
       setAlertMessage('Request has been processed.');
       setSeverity('success');
-      await loadRequests();
-      await loadPendingRequests();
+      setOpen(true);
+    } else {
+      setAlertMessage(`Error: ${result.error}`);
+      setSeverity('error');
+      setOpen(true);
     }
+    await loadRequests();
+    await loadPendingRequests();
   };
 
   const requestActions = [
-- 
GitLab


From ec0ad1cd2a64c226b32db371556cb183bfe2dac4 Mon Sep 17 00:00:00 2001
From: Brett Choquet <brett.choquet@inra.fr>
Date: Fri, 17 Jan 2025 00:30:00 +0100
Subject: [PATCH 2/2] Authentication and major rewriting

---
 .dockerignore                                |  22 +
 .gitignore                                   |   3 +
 .gitlab-ci.yml                               |  15 +
 Dockerfile                                   |  25 +
 env.sh                                       | 121 +++
 nginx/gzip.conf                              |  44 ++
 nginx/nginx.conf                             |  60 ++
 package.json                                 |  17 +-
 public/index.html                            |  29 +-
 src/actions/group.js                         | 149 ----
 src/actions/index.js                         |   8 -
 src/actions/policy.js                        | 262 -------
 src/actions/source.js                        | 336 --------
 src/actions/user.js                          | 322 --------
 src/components/App.js                        |  12 +-
 src/components/Header/Header.js              |  31 +-
 src/components/Layout/Layout.js              | 128 ++-
 src/components/Sidebar/Sidebar.js            |  10 +-
 src/context/InSylvaGatekeeperClient.js       | 307 --------
 src/context/InSylvaSourceManager.js          | 155 ----
 src/context/KeycloakClient.js                |  84 --
 src/context/UserContext.js                   | 101 ---
 src/images/logo.png                          | Bin 0 -> 23893 bytes
 src/images/mongo_logo.svg                    |   5 +
 src/index.js                                 |  52 +-
 src/pages/dashboard/Dashboard.js             |  69 +-
 src/pages/error/403.js                       |  44 ++
 src/pages/error/{Error.js => 404.js}         |  18 +-
 src/pages/fields/Fields.js                   | 256 +++---
 src/pages/groups/Groups.js                   | 121 +--
 src/pages/home/Home.js                       |  48 ++
 src/pages/home/package.json                  |   7 +
 src/pages/home/styles.js                     |  25 +
 src/pages/policies/AssignedPolicies.js       | 131 ++++
 src/pages/policies/NewPolicyForm.js          |  59 ++
 src/pages/policies/Policies.js               | 786 +++++--------------
 src/pages/policies/PolicyAssignment.js       |  68 ++
 src/pages/policies/PolicyGroupAssignment.js  |  62 ++
 src/pages/policies/PolicySourceAssignment.js |  69 ++
 src/pages/requests/Requests.js               |  74 +-
 src/pages/roles/Roles.js                     | 311 ++++----
 src/pages/sources/Sources.js                 | 240 +++---
 src/pages/users/Users.js                     | 253 ++----
 src/services/GatekeeperService.js            | 374 +++++++++
 src/store/CustomConnector.js                 |  53 --
 src/store/asyncEnhancer.js                   |  16 -
 src/store/index.js                           |  17 -
 src/store/useStore.js                        |  60 --
 src/utils.js                                 | 106 +--
 49 files changed, 2173 insertions(+), 3392 deletions(-)
 create mode 100644 .dockerignore
 create mode 100644 .gitlab-ci.yml
 create mode 100644 Dockerfile
 create mode 100755 env.sh
 create mode 100644 nginx/gzip.conf
 create mode 100644 nginx/nginx.conf
 delete mode 100644 src/actions/group.js
 delete mode 100644 src/actions/index.js
 delete mode 100644 src/actions/policy.js
 delete mode 100644 src/actions/source.js
 delete mode 100644 src/actions/user.js
 delete mode 100644 src/context/InSylvaGatekeeperClient.js
 delete mode 100644 src/context/InSylvaSourceManager.js
 delete mode 100644 src/context/KeycloakClient.js
 delete mode 100644 src/context/UserContext.js
 create mode 100644 src/images/logo.png
 create mode 100644 src/images/mongo_logo.svg
 create mode 100644 src/pages/error/403.js
 rename src/pages/error/{Error.js => 404.js} (77%)
 create mode 100644 src/pages/home/Home.js
 create mode 100644 src/pages/home/package.json
 create mode 100644 src/pages/home/styles.js
 create mode 100644 src/pages/policies/AssignedPolicies.js
 create mode 100644 src/pages/policies/NewPolicyForm.js
 create mode 100644 src/pages/policies/PolicyAssignment.js
 create mode 100644 src/pages/policies/PolicyGroupAssignment.js
 create mode 100644 src/pages/policies/PolicySourceAssignment.js
 create mode 100644 src/services/GatekeeperService.js
 delete mode 100644 src/store/CustomConnector.js
 delete mode 100644 src/store/asyncEnhancer.js
 delete mode 100644 src/store/index.js
 delete mode 100644 src/store/useStore.js

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..7dc10ba
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,22 @@
+# Ignore node_modules directory
+node_modules/
+
+# Ignore npm debug log
+npm-debug.log
+
+# Ignore build artifacts
+dist/
+build/
+out/
+
+# Ignore development files
+*.log
+*.pid
+*.lock
+
+# Ignore version control files
+.git/
+.gitignore
+
+# Ignore certificates
+ssl/
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index f5d62d3..de47805 100755
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,6 @@ yarn-error.log*
 
 # Misc
 .DS_Store
+
+ssl/*
+public/env-config.js
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..0591f3c
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,15 @@
+stages:
+  - build
+
+build:
+  stage: build
+  image: docker:latest
+  services:
+    - docker:dind
+  script:
+    - apk add jq
+    - version=$(jq -r .version package.json)
+    - docker build -t registry.forgemia.inra.fr/in-sylva-development/in-sylva.portal:$version .
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - docker push registry.forgemia.inra.fr/in-sylva-development/in-sylva.portal:$version
+  when: manual
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..4e5eee9
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,25 @@
+FROM node:18.20.5 as portal
+
+WORKDIR /app/
+COPY package.json .
+RUN yarn install
+COPY . .
+RUN yarn build
+
+FROM nginx:1.24-bullseye
+COPY --from=portal /app/build /usr/share/nginx/html
+
+RUN rm /etc/nginx/conf.d/default.conf
+COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
+COPY nginx/gzip.conf /etc/nginx/conf.d/gzip.conf
+
+WORKDIR /usr/share/nginx/html
+RUN chown -R :www-data /usr/share/nginx/html
+
+COPY ./env.sh .
+RUN chmod +x env.sh
+
+COPY .env.production .env
+RUN ./env.sh -e .env -o ./
+
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/env.sh b/env.sh
new file mode 100755
index 0000000..5c94083
--- /dev/null
+++ b/env.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+usage() {
+    BASENAME=$(basename "$0")
+    echo "Usage: $BASENAME -e <env-file> -o <output-file>"
+    echo "  -e, --env-file     Path to .env file"
+    echo "  -o, --output-file  Path to output '.env-config.js' file"
+    exit 1
+}
+
+while getopts "e:o:" opt; do
+    case $opt in
+    e)
+        ENV_FILE=$OPTARG
+        ;;
+    o)
+        OUT_DIRECTORY=$OPTARG
+        ;;
+    \?)
+        # Invalid option
+        echo "Invalid option: -$OPTARG"
+        usage
+        exit 1
+        ;;
+    :)
+        echo "Option -$OPTARG requires an argument."
+        usage
+        exit 1
+        ;;
+    esac
+done
+
+# Check if required options are provided
+if [ -z "$OUT_DIRECTORY" ]; then
+    echo "Error: -o (output directory) is required."
+    echo ""
+    usage
+    exit 1
+fi
+
+if [ -z "$ENV_FILE" ]; then
+    echo "Error: -e (environment file) is required."
+    echo ""
+    usage
+    exit 1
+fi
+
+ENV_FILE_PATH=$(realpath $ENV_FILE)
+
+# Check if the environment file exists
+if [[ ! -f $ENV_FILE_PATH ]]; then
+    echo "Environment file does not exist"
+    echo ""
+    usage
+    exit 1
+fi
+
+# Check if the environment file is readable
+if [[ ! -r $ENV_FILE_PATH ]]; then
+    echo "Environment file is not readable"
+    echo ""
+    usage
+    exit 1
+fi
+
+# Check if the environment file is empty
+if [[ ! -s $ENV_FILE_PATH ]]; then
+    echo "Environment file is empty"
+    echo ""
+    usage
+    exit 1
+fi
+
+# Check if the environment file has the correct format
+BAD_LINES=$(grep -v -P '^[^=\s]+=[^=\s]+$' "$ENV_FILE_PATH")
+if [ -n "$BAD_LINES" ]; then
+    echo "Environment file has incorrect format or contains empty values:"
+    echo "$BAD_LINES"
+    echo ""
+    usage
+    exit 1
+fi
+
+FULL_PATH_OUTPUT_DIRECTORY=$(realpath $OUT_DIRECTORY)
+
+# Check if the output directory is a directory, exists, and can be written
+if [[ ! -d $FULL_PATH_OUTPUT_DIRECTORY ]]; then
+    echo "Output directory does not exist or is not a directory"
+    echo ""
+    usage
+    exit 1
+fi
+
+if [[ ! -w $FULL_PATH_OUTPUT_DIRECTORY ]]; then
+    echo "Output directory is not writable"
+    echo ""
+    usage
+    exit 1
+fi
+
+OUTPUT_FILE="env-config.js"
+FULL_OUTPUT_PATH="$FULL_PATH_OUTPUT_DIRECTORY/$OUTPUT_FILE"
+
+# Remove the output file if it exists
+if [[ -f $FULL_OUTPUT_PATH ]]; then
+    rm $FULL_OUTPUT_PATH
+fi
+
+# Add assignment
+echo "window._env_ = {" >>$FULL_OUTPUT_PATH
+
+while read -r line || [[ -n "$line" ]]; do
+    # Split env variables by '='
+    varname=$(echo $line | cut -d'=' -f1)
+    value=$(echo $line | cut -d'=' -f2)
+
+    # Append configuration property to JS file
+    echo "  $varname: \"$value\"," >>$FULL_OUTPUT_PATH
+done <$ENV_FILE_PATH
+
+echo "}" >>$FULL_OUTPUT_PATH
diff --git a/nginx/gzip.conf b/nginx/gzip.conf
new file mode 100644
index 0000000..2f54ae1
--- /dev/null
+++ b/nginx/gzip.conf
@@ -0,0 +1,44 @@
+# Enable Gzip compressed.
+# gzip on;
+
+  # Enable compression both for HTTP/1.0 and HTTP/1.1 (required for CloudFront).
+  gzip_http_version  1.0;
+
+  # Compression level (1-9).
+  # 5 is a perfect compromise between size and cpu usage, offering about
+  # 75% reduction for most ascii files (almost identical to level 9).
+  gzip_comp_level    5;
+
+  # Don't compress anything that's already small and unlikely to shrink much
+  # if at all (the default is 20 bytes, which is bad as that usually leads to
+  # larger files after gzipping).
+  gzip_min_length    256;
+
+  # Compress data even for clients that are connecting to us via proxies,
+  # identified by the "Via" header (required for CloudFront).
+  gzip_proxied       any;
+
+  # Tell proxies to cache both the gzipped and regular version of a resource
+  # whenever the client's Accept-Encoding capabilities header varies;
+  # Avoids the issue where a non-gzip capable client (which is extremely rare
+  # today) would display gibberish if their proxy gave them the gzipped version.
+  gzip_vary          on;
+
+  # Compress all output labeled with one of the following MIME-types.
+  gzip_types
+    application/atom+xml
+    application/javascript
+    application/json
+    application/rss+xml
+    application/vnd.ms-fontobject
+    application/x-font-ttf
+    application/x-web-app-manifest+json
+    application/xhtml+xml
+    application/xml
+    font/opentype
+    image/svg+xml
+    image/x-icon
+    text/css
+    text/plain
+    text/x-component;
+  # text/html is always compressed by HttpGzipModule
\ No newline at end of file
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
new file mode 100644
index 0000000..e3c6319
--- /dev/null
+++ b/nginx/nginx.conf
@@ -0,0 +1,60 @@
+include /etc/nginx/mime.types;
+
+server {
+
+    listen 80;
+    server_name -;
+
+    ssl_certificate /etc/ssl/fullchain.pem;
+    ssl_certificate_key /etc/ssl/fullchain.pem.key;
+
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Host $host;
+    proxy_set_header X-Forwarded-Server $host;
+    proxy_set_header X-Forwarded-Port $server_port;
+    proxy_set_header X-Forwarded-Proto $scheme;
+
+    access_log /var/log/nginx/host.access.log;
+    error_log /var/log/nginx/host.error.log;
+
+    root /usr/share/nginx/html;
+    index index.html index.htm;
+
+    location /static/media/ {
+        try_files $uri /usr/share/nginx/html/static/media;
+    }
+
+    location / {
+
+        root /usr/share/nginx/html;
+        index index.html;
+        autoindex on;
+        set $fallback_file /index.html;
+        if ($http_accept !~ text/html) {
+            set $fallback_file /null;
+        }
+        if ($uri ~ /$) {
+            set $fallback_file /null;
+        }
+        try_files $uri $fallback_file;
+
+        proxy_http_version 1.1;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection 'upgrade';
+        proxy_set_header Host $host;
+        proxy_cache_bypass $http_upgrade;
+
+        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
+        add_header 'Access-Control-Allow-Credentials' 'true' always;
+        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
+        add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
+    }
+
+    error_page 500 502 503 504 /50x.html;
+
+    location = /50x.html {
+        root /usr/share/nginx/html;
+    }
+}
diff --git a/package.json b/package.json
index b3e53d7..e3f8cc4 100644
--- a/package.json
+++ b/package.json
@@ -1,31 +1,32 @@
 {
   "name": "in-sylva.portal",
-  "version": "1.0.0",
+  "version": "1.1.1-alpha",
   "private": true,
   "homepage": ".",
   "dependencies": {
     "@elastic/datemath": "^5.0.3",
     "@elastic/eui": "^27.4.0",
-    "@in-sylva/json-view": "git+ssh://git@forgemia.inra.fr:in-sylva-development/json-view.git",
-    "@in-sylva/react-use-storage": "git+ssh://git@forgemia.inra.fr:in-sylva-development/react-use-storage.git",
     "@material-ui/core": "^4.11.0",
     "@material-ui/icons": "^4.9.1",
     "@material-ui/lab": "^4.0.0-alpha.48",
     "@material-ui/styles": "^4.10.0",
+    "@microlink/react-json-view": "^1.23.1",
     "moment": "^2.27.0",
     "mui-datatables": "^3.4.0",
+    "oidc-client-ts": "^3.1.0",
     "papaparse": "5.3.0",
     "react": "^16.13.1",
     "react-apexcharts": "^1.3.3",
     "react-dom": "^16.13.1",
+    "react-oidc-context": "^3.2.0",
     "react-router-dom": "^5.2.0",
     "react-scripts": "^3.3.0",
     "recharts": "^2.0.0-beta.1",
     "tinycolor2": "^1.4.1"
   },
   "scripts": {
-    "start": "react-scripts start",
-    "build": "react-scripts build",
+    "start": "./env.sh -e .env.development -o ./public && BROWSER=none NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
+    "build": "NODE_OPTIONS=--openssl-legacy-provider react-scripts build",
     "test": "react-scripts test",
     "eject": "react-scripts eject",
     "lint": "eslint ./src",
@@ -47,10 +48,10 @@
   "devDependencies": {
     "eslint-config-prettier": "^9.1.0",
     "eslint-plugin-prettier": "^5.1.3",
-    "lint-staged": "14.0.1",
     "husky": "8.0.3",
-    "prettier": "^3.2.5",
-    "jscs": "^3.0.7"
+    "jscs": "^3.0.7",
+    "lint-staged": "14.0.1",
+    "prettier": "^3.2.5"
   },
   "husky": {
     "hooks": {
diff --git a/public/index.html b/public/index.html
index e4c2254..8661142 100755
--- a/public/index.html
+++ b/public/index.html
@@ -1,12 +1,13 @@
 <!DOCTYPE html>
 <html lang="en">
-<head>
-  <meta charset="utf-8" />
-  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png" />
-  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
-  <meta name="theme-color" content="#000000" />
-  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
-  <!--
+  <head>
+    <meta charset="utf-8" />
+    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png" />
+    <meta name="viewport"
+      content="width=device-width, initial-scale=1, shrink-to-fit=no" />
+    <meta name="theme-color" content="#000000" />
+    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
+    <!--
       Notice the use of %PUBLIC_URL% in the tags above.
       It will be replaced with the URL of the `public` folder during the build.
       Only files inside the `public` folder can be referenced from the HTML.
@@ -15,11 +16,11 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
-  <title>IN-SYLVA Portal</title>
-  <script src="%PUBLIC_URL%/env-config.js"></script>
-</head>
-<body style="font-family: 'Roboto', sans-serif;">
-  <noscript>You need to enable JavaScript to run this app.</noscript>
-  <div id="root"></div>
-</body>
+    <title>IN-SYLVA Portal</title>
+    <script src="%PUBLIC_URL%/env-config.js"></script>
+  </head>
+  <body style="font-family: 'Roboto', sans-serif;">
+    <noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+  </body>
 </html>
diff --git a/src/actions/group.js b/src/actions/group.js
deleted file mode 100644
index 9aaf645..0000000
--- a/src/actions/group.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import { InSylvaGatekeeperClient } from '../context/InSylvaGatekeeperClient';
-import { getGatekeeperBaseUrl } from '../utils';
-
-const igClient = new InSylvaGatekeeperClient();
-igClient.baseUrl = getGatekeeperBaseUrl();
-
-export const createGroup = async (store, name, description, kcId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const group = await request.createGroup({ name, description, kcId });
-    if (group) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return group;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getGroups = async (store, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groups = await request.getGroups();
-    if (groups) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groups;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createGroupUser = async (store, groupId, kcId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupUser = await request.createGroupUser({ groupId, kcId });
-    if (groupUser) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupUser;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getGroupUsers = async (store, groupId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupUser = await request.getGroupUsers({ groupId });
-    if (groupUser) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupUser;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createGroupPolicy = async (store, groupId, policyId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupPolicy = await request.createGroupPolicy({ groupId, policyId });
-    if (groupPolicy) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupPolicy;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteGroup = async (store, groupId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupUser = await request.deleteGroup({ id: groupId });
-    if (groupUser) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupUser;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteGroupPolicy = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupPolicy = await request.deleteGroupPolicy({ id });
-    if (groupPolicy) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupPolicy;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteGroupUser = async (store, groupId, userId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const groupPolicy = await request.deleteGroupUser({ groupId, userId });
-    if (groupPolicy) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return groupPolicy;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
diff --git a/src/actions/index.js b/src/actions/index.js
deleted file mode 100644
index 65fb44f..0000000
--- a/src/actions/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import * as user from './user';
-import * as source from './source';
-import * as policy from './policy';
-import * as group from './group';
-export { user };
-export { source };
-export { policy };
-export { group };
diff --git a/src/actions/policy.js b/src/actions/policy.js
deleted file mode 100644
index 1cd9e24..0000000
--- a/src/actions/policy.js
+++ /dev/null
@@ -1,262 +0,0 @@
-import { InSylvaGatekeeperClient } from '../context/InSylvaGatekeeperClient';
-import { getGatekeeperBaseUrl } from '../utils';
-
-const igClient = new InSylvaGatekeeperClient();
-igClient.baseUrl = getGatekeeperBaseUrl();
-
-export const createPolicy = async (store, name, kcId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.createPolicy({ name, kcId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createPolicyField = async (
-  store,
-  policyId,
-  stdFieldId,
-  request = igClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.createPolicyField({ policyId, stdFieldId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const updatePolicy = async (
-  store,
-  id,
-  name,
-  sourceId,
-  isDefault,
-  request = igClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.updatePolicy({ id, name, sourceId, isDefault });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const updatePolicyField = async (
-  store,
-  id,
-  policyId,
-  stdFieldId,
-  request = igClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.updatePolicyField({ id, policyId, stdFieldId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deletePolicyField = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.deletePolicyField({ id });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deletePolicy = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.deletePolicy({ id });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getPolicies = async (store, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getPolicies({});
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getPoliciesByUser = async (store, kc_id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getPoliciesByUser(kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getPoliciesWithSourcesByUser = async (store, kc_id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getPoliciesWithSourcesByUser(kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getAssignedPolicies = async (store, policyId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getAssignedPolicies({ policyId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getPoliciesWithSources = async (store, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getPoliciesWithSources();
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getGroupDetailsByPolicy = async (store, policyId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.getGroupDetailsByPolicy({ policyId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createPolicySource = async (
-  store,
-  policyId,
-  sourceId,
-  request = igClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.createPolicySource({ policyId, sourceId });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
diff --git a/src/actions/source.js b/src/actions/source.js
deleted file mode 100644
index cf41d7d..0000000
--- a/src/actions/source.js
+++ /dev/null
@@ -1,336 +0,0 @@
-import { InSylvaSourceManager } from '../context/InSylvaSourceManager';
-
-const smClient = new InSylvaSourceManager();
-smClient.baseUrl = process.env.REACT_APP_IN_SYLVA_SOURCE_MANAGER_PORT
-  ? `${process.env.REACT_APP_IN_SYLVA_SOURCE_MANAGER_HOST}:${process.env.REACT_APP_IN_SYLVA_SOURCE_MANAGER_PORT}`
-  : `${window._env_.REACT_APP_IN_SYLVA_SOURCE_MANAGER_HOST}`;
-
-export const createSource = async (
-  store,
-  metaUrfms,
-  name,
-  description,
-  kc_id,
-  request = smClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.createSource(metaUrfms, name, description, kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const sources = async (store, kc_id, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.sources(kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const indexedSources = async (store, kc_id, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.indexedSources(kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createStdField = async (
-  store,
-  category,
-  field_name,
-  definition_and_comment,
-  obligation_or_condition,
-  field_type,
-  cardinality,
-  values,
-  isPublic,
-  isOptional,
-  request = smClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.addStdField(
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional
-    );
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const createAddtlField = async (
-  store,
-  category,
-  field_name,
-  definition_and_comment,
-  obligation_or_condition,
-  field_type,
-  cardinality,
-  values,
-  isPublic,
-  isOptional,
-  request = smClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.addAddtlField(
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional
-    );
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const updateStdField = async (
-  store,
-  category,
-  field_name,
-  definition_and_comment,
-  obligation_or_condition,
-  field_type,
-  cardinality,
-  values,
-  isPublic,
-  isOptional,
-  request = smClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.updateStdField(
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional
-    );
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const updateSource = async (store, kc_id, source_id, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.updateSource(kc_id, source_id);
-
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const publicFields = async (store, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const stdFields = await request.publicFields();
-
-    if (stdFields) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return stdFields;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const privateFields = async (store, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const stdFields = await request.privateFields();
-
-    if (stdFields) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return stdFields;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const allSources = async (store, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const result = await request.allSource();
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const allIndexedSources = async (store, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const result = await request.allIndexedSource();
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const truncateStdField = async (store, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const result = await request.truncateStdField();
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteSource = async (store, sourceId, kc_id, request = smClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const result = await request.deleteSource(sourceId, kc_id);
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const mergeAndSendSource = async (
-  store,
-  kc_id,
-  name,
-  description,
-  sources,
-  request = smClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const result = await request.mergeAndSendSource({
-      kc_id,
-      name,
-      description,
-      sources,
-    });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return result;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
diff --git a/src/actions/user.js b/src/actions/user.js
deleted file mode 100644
index 180a086..0000000
--- a/src/actions/user.js
+++ /dev/null
@@ -1,322 +0,0 @@
-import { InSylvaGatekeeperClient } from '../context/InSylvaGatekeeperClient';
-import { getGatekeeperBaseUrl } from '../utils';
-
-const igClient = new InSylvaGatekeeperClient();
-igClient.baseUrl = getGatekeeperBaseUrl();
-
-export const createUser = async (
-  store,
-  username,
-  email,
-  password,
-  roleId,
-  request = igClient
-) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const nUser = await request.createUser({ username, email, password, roleId });
-    if (nUser) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const findUser = async (store, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const users = await request.findUser();
-    if (users) {
-      const status = 'SUCCESS';
-      store.setState({ users, status, isLoading: false });
-      return users;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const updateUser = async (store, user, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.updateUser({
-      id: user.id,
-      firstName: user.firstName,
-      lastName: user.lastName,
-    });
-    if (result) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const findOneUser = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const user = await request.findOneUser(id);
-
-    if (user) {
-      const status = 'SUCCESS';
-      store.setState({ user: user, status, isLoading: false });
-      return user;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const findOneUserWithGroupAndRole = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const user = await request.findOneUserWithGroupAndRole(id);
-
-    if (user) {
-      const status = 'SUCCESS';
-      store.setState({ user: user, status, isLoading: false });
-      return user;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteUser = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const user = await request.deleteUser({ id: id });
-    if (user) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export async function fetchRequests(store, request = igClient) {
-  store.setState({ isLoading: true });
-  request.token = sessionStorage.getItem('access_token');
-  try {
-    const requests = await request.getRequests();
-    if (requests) {
-      return requests;
-    }
-  } catch (error) {
-    console.error(error);
-  }
-}
-
-export async function fetchPendingRequests(store, request = igClient) {
-  store.setState({ isLoading: true });
-  request.token = sessionStorage.getItem('access_token');
-  try {
-    const requests = await request.getPendingRequests();
-    if (requests) {
-      return requests;
-    }
-  } catch (error) {
-    console.error(error);
-  }
-}
-
-export const processUserRequest = async (store, requestId) => {
-  store.setState({ isLoading: true });
-  igClient.token = sessionStorage.getItem('access_token');
-  try {
-    return await igClient.processUserRequest(requestId);
-  } catch (error) {
-    console.error(error);
-  }
-};
-
-export const deleteUserRequest = async (store, requestId) => {
-  store.setState({ isLoading: true });
-  igClient.token = sessionStorage.getItem('access_token');
-  try {
-    return await igClient.deleteUserRequest(requestId);
-  } catch (error) {
-    console.error(error);
-  }
-};
-
-export const createRole = async (store, name, description, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const role = await request.createRole({ name: name, description: description });
-    if (role) {
-      const status = 'SUCCESS';
-      store.setState({ role, status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const findRole = async (store, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const roles = await request.findRole();
-    if (roles) {
-      const status = 'SUCCESS';
-      store.setState({ roles, status, isLoading: false });
-      return roles;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const allocateRoles = async (store, roles, users, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.allocateRoles({ roles, users });
-    if (result === true) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const allocateRolesToUser = async (store, userId, roleId, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const result = await request.allocateRolesToUser({ userId, roleId });
-    if (result === true) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const allocatedRoles = async (store, kc_id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-
-    const allocatedRoles = await request.allocatedRoles(kc_id);
-    if (allocatedRoles) {
-      const status = 'SUCCESS';
-      store.setState({ allocatedRoles, status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const setKcId = async (store, email, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const { kc_id } = await request.kcId(email);
-
-    store.setState({ kcId: kc_id });
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const deleteRole = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const role = await request.deleteRole({ id });
-
-    if (role) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const getAssignedUserByRole = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const assignedUserByRole = await request.getAssignedUserByRole({ id });
-
-    if (assignedUserByRole) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return assignedUserByRole;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
-
-export const usersWithGroupAndRole = async (store, id, request = igClient) => {
-  try {
-    store.setState({ isLoading: true });
-    request.token = sessionStorage.getItem('access_token');
-    const usersWithGroupAndRole = await request.usersWithGroupAndRole();
-
-    if (usersWithGroupAndRole) {
-      const status = 'SUCCESS';
-      store.setState({ status, isLoading: false });
-      return usersWithGroupAndRole;
-    }
-  } catch (error) {
-    const isError404 = error.response && error.response.status === 404;
-    const status = isError404 ? 'NOT_FOUND' : 'ERROR';
-    store.setState({ status, isLoading: false });
-  }
-};
diff --git a/src/components/App.js b/src/components/App.js
index 1476783..9812ec8 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -1,16 +1,18 @@
 import React from 'react';
 import { HashRouter, Route, Switch, Redirect } from 'react-router-dom';
 import Layout from './Layout';
-import Error from '../pages/error';
+import Error404 from '../pages/error/404';
+import Error403 from '../pages/error/403';
 
 export default function App() {
   return (
     <HashRouter>
       <Switch>
-        <Route exact path="/" render={() => <Redirect to="/app/dashboard" />} />
-        <Route exact path="/app" render={() => <Redirect to="/app/dashboard" />} />
-        <Route path="/app" component={Layout} />
-        <Route path="/Error" component={Error} />
+        <Route exact path="/" render={() => <Redirect to="/home" />} />
+        <Route path="/not-found" component={Error404} />
+        <Route path="/forbidden" component={Error403} />
+        <Route path="/" component={Layout} />
+        <Route render={() => <Redirect to="/not-found" />} />
       </Switch>
     </HashRouter>
   );
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
index a534bad..6c09d23 100644
--- a/src/components/Header/Header.js
+++ b/src/components/Header/Header.js
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useCallback } from 'react';
+import React, { useState } from 'react';
 import { AppBar, Toolbar, IconButton, Menu } from '@material-ui/core';
 import {
   Menu as MenuIcon,
@@ -13,30 +13,15 @@ import {
   useLayoutDispatch,
   toggleSidebar,
 } from '../../context/LayoutContext';
-import { useUserDispatch, signOut } from '../../context/UserContext';
-import store from '../../store/index';
+import { useAuth } from 'react-oidc-context';
 
-export default function Header(props) {
+export default function Header({ email }) {
   const classes = useStyles();
-  let [, globalActions] = store();
   const layoutState = useLayoutState();
   const layoutDispatch = useLayoutDispatch();
-  const userDispatch = useUserDispatch();
-  let [user, setUser] = useState({});
+  const auth = useAuth();
   let [profileMenu, setProfileMenu] = useState(null);
 
-  const loadUser = useCallback(async () => {
-    if (sessionStorage.getItem('userId')) {
-      const userId = sessionStorage.getItem('userId');
-      const user = await globalActions.user.findOneUser(userId);
-      setUser(user);
-    }
-  }, [globalActions]);
-
-  useEffect(() => {
-    loadUser();
-  }, [loadUser]);
-
   return (
     <AppBar position="fixed" className={classes.appBar}>
       <Toolbar className={classes.toolbar}>
@@ -87,14 +72,18 @@ export default function Header(props) {
           <div className={classes.profileMenuUser}>
             <div className={classes.profileMenuItem}>
               <Typography variant="h4" weight="medium">
-                {user.username}
+                {email}
               </Typography>
             </div>
             <div className={classes.profileMenuItem}>
               <Typography
                 className={classes.profileMenuLink}
                 color="primary"
-                onClick={() => signOut(userDispatch, props.history)}
+                onClick={async () => {
+                  await auth.signoutRedirect({
+                    post_logout_redirect_uri: `${process.env.REACT_APP_BASE_URL}`,
+                  });
+                }}
               >
                 Sign out
               </Typography>
diff --git a/src/components/Layout/Layout.js b/src/components/Layout/Layout.js
index f2240a9..239296a 100644
--- a/src/components/Layout/Layout.js
+++ b/src/components/Layout/Layout.js
@@ -1,9 +1,10 @@
-import React from 'react';
-import { Route, Switch, withRouter } from 'react-router-dom';
+import React, { useState, useEffect } from 'react';
+import { Route, Switch, withRouter, Redirect } from 'react-router-dom';
 import classnames from 'classnames';
 import useStyles from './styles';
 import Header from '../Header';
 import Sidebar from '../Sidebar';
+import Home from '../../pages/home';
 import Dashboard from '../../pages/dashboard';
 import Users from '../../pages/users';
 import Roles from '../../pages/roles/Roles';
@@ -13,35 +14,112 @@ import Fields from '../../pages/fields';
 import Policies from '../../pages/policies';
 import Groups from '../../pages/groups/Groups';
 import { useLayoutState } from '../../context/LayoutContext';
+import { useAuth } from 'react-oidc-context';
+import { createUser, findUserBySub } from '../../services/GatekeeperService';
+
+const ProtectedRoute = ({ isAllowed, redirectPath = '/forbidden', path, component }) => {
+  if (!isAllowed) {
+    return <Redirect to={redirectPath} />;
+  }
+  return <Route path={path} component={component} />;
+};
 
 function Layout(props) {
   const classes = useStyles();
   const layoutState = useLayoutState();
+  const auth = useAuth();
+  const [user, setUser] = useState(null);
+  const [roles, setRoles] = useState([]);
+
+  useEffect(() => {
+    const fetchUser = async (sub) => {
+      let user = await findUserBySub(sub);
+      if (!user.id) {
+        // User registered on Keycloak but not in the database
+        if (auth.user?.profile?.email) {
+          const result = await createUser(sub, auth.user?.profile?.email);
+
+          if (result) {
+            user = await findUserBySub(sub);
+          } else {
+            auth.signoutRedirect();
+          }
+        }
+      }
+      setUser(user);
+      setRoles(user.roles.map((r) => r.role_id));
+    };
+    if (!auth || auth.isLoading) {
+      return;
+    }
+    if (auth.isAuthenticated) {
+      fetchUser(auth.user.profile.sub);
+    } else {
+      auth.signinRedirect();
+    }
+  }, [auth]);
 
   return (
-    <div className={classes.root}>
-      <>
-        <Header history={props.history} />
-        <Sidebar />
-        <div
-          className={classnames(classes.content, {
-            [classes.contentShift]: layoutState.isSidebarOpened,
-          })}
-        >
-          <div className={classes.fakeToolbar} />
-          <Switch>
-            <Route path="/app/dashboard" component={Dashboard} />
-            <Route path="/app/users" component={Users} />
-            <Route path="/app/roles" component={Roles} />
-            <Route path="/app/groups" component={Groups} />
-            <Route path="/app/requests" component={Requests} />
-            <Route path="/app/policies" component={Policies} />
-            <Route path="/app/sources" component={Sources} />
-            <Route path="/app/fields" component={Fields} />
-          </Switch>
-        </div>
-      </>
-    </div>
+    user &&
+    roles.length > 0 && (
+      <div className={classes.root}>
+        <>
+          <Header email={user.email} usehistory={props.history} />
+          <Sidebar roles={roles} />
+          <div
+            className={classnames(classes.content, {
+              [classes.contentShift]: layoutState.isSidebarOpened,
+            })}
+          >
+            <div className={classes.fakeToolbar} />
+            <Switch>
+              <Route path="/home" component={Home} />
+              <ProtectedRoute
+                path="/dashboard"
+                isAllowed={roles.includes(1)}
+                component={Dashboard}
+              />
+              <ProtectedRoute
+                path="/users"
+                isAllowed={roles.includes(1)}
+                component={Users}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1)}
+                path="/roles"
+                component={Roles}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1)}
+                path="/groups"
+                component={Groups}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1)}
+                path="/requests"
+                component={Requests}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1)}
+                path="/policies"
+                component={Policies}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1) || roles.includes(2)}
+                path="/sources"
+                component={Sources}
+              />
+              <ProtectedRoute
+                isAllowed={roles.includes(1) || roles.includes(2)}
+                path="/fields"
+                component={Fields}
+              />
+              <Route render={() => <Redirect to="/not-found" />} />
+            </Switch>
+          </div>
+        </>
+      </div>
+    )
   );
 }
 
diff --git a/src/components/Sidebar/Sidebar.js b/src/components/Sidebar/Sidebar.js
index dc3b4e6..e6a2006 100644
--- a/src/components/Sidebar/Sidebar.js
+++ b/src/components/Sidebar/Sidebar.js
@@ -11,20 +11,18 @@ import {
   useLayoutDispatch,
   toggleSidebar,
 } from '../../context/LayoutContext';
-import { getSideBarItems, getUserRoleId } from '../../utils';
+import { getSideBarItems } from '../../utils';
 
-const Sidebar = ({ location }) => {
+const Sidebar = ({ location, roles }) => {
   const classes = useStyles();
   const theme = useTheme();
   let { isSidebarOpened } = useLayoutState();
   const layoutDispatch = useLayoutDispatch();
   let [isPermanent, setPermanent] = useState(true);
   const [sidebarItems, setSidebarItems] = useState([]);
-  const [userRoleId, setUserRoleId] = useState(0);
 
   useEffect(() => {
     setSidebarItems(getSideBarItems());
-    setUserRoleId(getUserRoleId());
     const handleWindowWidthChange = () => {
       const windowWidth = window.innerWidth;
       const breakpointWidth = theme.breakpoints.values.md;
@@ -41,11 +39,11 @@ const Sidebar = ({ location }) => {
     return function cleanup() {
       window.removeEventListener('resize', handleWindowWidthChange);
     };
-  }, [setSidebarItems, setUserRoleId, isPermanent, theme]);
+  }, [setSidebarItems, isPermanent, theme]);
 
   const buildSidebarItems = () => {
     return sidebarItems.map((item) => {
-      if (item.roles.some((authorizedRoleId) => authorizedRoleId === userRoleId)) {
+      if (item.roles.some((authorizedRoleId) => roles.includes(authorizedRoleId))) {
         return (
           <SidebarLink
             key={item.id}
diff --git a/src/context/InSylvaGatekeeperClient.js b/src/context/InSylvaGatekeeperClient.js
deleted file mode 100644
index f976cd7..0000000
--- a/src/context/InSylvaGatekeeperClient.js
+++ /dev/null
@@ -1,307 +0,0 @@
-class InSylvaGatekeeperClient {
-  async post(method, path, requestContent) {
-    const headers = {
-      'Content-Type': 'application/json',
-      'Access-Control-Allow-Origin': '*',
-      Authorization: `Bearer ${this.token}`,
-    };
-
-    const response = await fetch(`${this.baseUrl}${path}`, {
-      method: method,
-      headers,
-      body: JSON.stringify(requestContent),
-      mode: 'cors',
-    });
-    return await response.json();
-  }
-
-  async createUser({ username, email, password, roleId }) {
-    const path = `/user`;
-    return await this.post('POST', `${path}`, {
-      username,
-      email,
-      password,
-      roleId,
-    });
-  }
-
-  async kcId({ email }) {
-    const path = `/user/kcid`;
-
-    return await this.post('POST', `${path}`, {
-      email,
-    });
-  }
-
-  async updateUser({ id, firstName, lastName }) {
-    const path = `/user/update`;
-    return await this.post('PUT', `${path}`, {
-      id,
-      firstName,
-      lastName,
-    });
-  }
-
-  async findUser() {
-    const path = `/user/find`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async findOneUser(id) {
-    const path = `/user/findOne`;
-    return await this.post('POST', `${path}`, {
-      id,
-    });
-  }
-
-  async deleteUser({ id }) {
-    const path = `/user/delete`;
-    return await this.post('DELETE', `${path}`, {
-      userId: id,
-    });
-  }
-
-  async getRequests() {
-    const path = `/user/list-requests`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async getPendingRequests() {
-    const path = `/user/list-pending-requests`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async processUserRequest(id) {
-    const path = `/user/process-request`;
-    return await this.post('POST', `${path}`, {
-      id,
-    });
-  }
-
-  async deleteUserRequest(id) {
-    const path = `/user/delete-request`;
-    return await this.post('DELETE', `${path}`, {
-      id,
-    });
-  }
-
-  async createRole({ name, description }) {
-    const path = `/role`;
-    return await this.post('POST', `${path}`, {
-      name,
-      description,
-    });
-  }
-
-  async findRole() {
-    const path = `/role/find`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async allocateRoles({ roles, users }) {
-    try {
-      const path = `/allocate-role-to-user`;
-      for (let x = 0; x < users.length; x++) {
-        for (let y = 0; y < roles.length; y++) {
-          await this.post('POST', `${path}`, {
-            kc_id: users[x],
-            role_id: roles[y],
-          });
-        }
-      }
-      return true;
-    } catch (error) {
-      return false;
-    }
-  }
-
-  async allocateRolesToUser({ userId, roleId }) {
-    const path = `/allocate-role-to-user`;
-    return await this.post('POST', `${path}`, {
-      kc_id: userId,
-      role_id: roleId,
-    });
-  }
-  async allocatedRoles(kc_id) {
-    const path = `/allocatedRoles`;
-    return await this.post('POST', `${path}`, {
-      kc_id,
-    });
-  }
-
-  async createPolicy({ name, kcId }) {
-    const path = `/policy/add`;
-    return await this.post('POST', `${path}`, {
-      name,
-      kcId,
-    });
-  }
-
-  async createPolicyField({ policyId, stdFieldId }) {
-    const path = `/policyField/add`;
-    return await this.post('POST', `${path}`, {
-      policyId,
-      stdFieldId,
-    });
-  }
-
-  async updatePolicy({ id, name, sourceId, isDefault }) {
-    const path = `/policy/update`;
-    return await this.post('PUT', `${path}`, {
-      id,
-      name,
-      sourceId,
-      isDefault,
-    });
-  }
-
-  async updatePolicyField({ id, policyId, stdFieldId }) {
-    const path = `/policyField/update`;
-    return this.post('PUT', `${path}`, {
-      id,
-      policyId,
-      stdFieldId,
-    });
-  }
-
-  async deletePolicyField({ id }) {
-    const path = `/policyField/delete`;
-    return await this.post('DELETE', `${path}`, {
-      id,
-    });
-  }
-
-  async deletePolicy({ id }) {
-    const path = `/policy/delete`;
-    return await this.post('DELETE', `${path}`, {
-      id,
-    });
-  }
-
-  async getPolicies() {
-    const path = `/policy/list`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async getPoliciesByUser(kcId) {
-    const path = `/policy/list-by-user`;
-    return await this.post('POST', `${path}`, { kcId });
-  }
-
-  async getPoliciesWithSourcesByUser(kcId) {
-    const path = `/policy/policies-with-sources-by-user`;
-    return await this.post('POST', `${path}`, { kcId });
-  }
-
-  async getPoliciesWithSources() {
-    const path = `/policy/policies-with-sources`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async getPolicyFields() {
-    const path = `/policyField/list`;
-    return await this.post('GET', `${path}`, {});
-  }
-
-  async getGroups() {
-    const path = `/user/groups`;
-    return await this.post('POST', `${path}`, {});
-  }
-
-  async getGroupPolicies() {
-    const path = `/user/group-policies`;
-    return await this.post('GET', `${path}`, {});
-  }
-
-  async getGroupUsers({ groupId }) {
-    const path = `/user/group-users`;
-    return await this.post('POST', `${path}`, { groupId });
-  }
-
-  async createGroup({ name, description, kcId }) {
-    const path = `/user/add-group`;
-    return await this.post('POST', `${path}`, { name, description, kcId });
-  }
-
-  async createGroupPolicy({ groupId, policyId }) {
-    const path = `/user/add-group-policy`;
-    return await this.post('POST', `${path}`, { groupId, policyId });
-  }
-
-  async createGroupUser({ groupId, kcId }) {
-    const path = `/user/add-group-user`;
-    return await this.post('POST', `${path}`, { groupId, kcId });
-  }
-
-  async updateGroup({ id, userId, name, description }) {
-    const path = `/user/update-group`;
-    return await this.post('PUT', `${path}`, { name, description, id, userId });
-  }
-
-  async updateGroupPolicy({ id, groupId, policyId }) {
-    const path = `/user/update-group-policy`;
-    return await this.post('PUT', `${path}`, { id, groupId, policyId });
-  }
-
-  async updateGroupUser({ id, kcId, groupId }) {
-    const path = `/user/update-group-user`;
-    return await this.post('PUT', `${path}`, { id, kcId, groupId });
-  }
-
-  async deleteGroup({ id }) {
-    const path = `/user/delete-group`;
-    return await this.post('DELETE', `${path}`, { id });
-  }
-
-  async deleteGroupPolicy({ id }) {
-    const path = `/user/delete-group-policy`;
-    return await this.post('DELETE', `${path}`, { id });
-  }
-
-  async deleteGroupUser({ groupId, userId }) {
-    const path = `/user/delete-group-user`;
-    return await this.post('DELETE', `${path}`, { groupId, userId });
-  }
-
-  async getAssignedPolicies({ policyId }) {
-    const path = `/policy/assigned-fields`;
-    return await this.post('POST', `${path}`, { policyId });
-  }
-
-  async deleteRole({ id }) {
-    const path = `/role/delete`;
-    return await this.post('DELETE', `${path}`, { id });
-  }
-
-  async getAssignedUserByRole({ id }) {
-    const path = `/user/assigned-by-role`;
-    return await this.post('POST', `${path}`, { id });
-  }
-
-  async getGroupDetailsByPolicy({ policyId }) {
-    const path = `/policy/policies-with-groups`;
-    return await this.post('POST', `${path}`, { policyId });
-  }
-
-  async usersWithGroupAndRole() {
-    const path = `/user/with-groups-and-roles`;
-    return await this.post('GET', `${path}`);
-  }
-
-  async findOneUserWithGroupAndRole(id) {
-    const path = `/user/one-with-groups-and-roles`;
-    return await this.post('POST', `${path}`, {
-      id,
-    });
-  }
-
-  async createPolicySource({ policyId, sourceId }) {
-    const path = `/policySource/add`;
-    return await this.post('POST', `${path}`, { policyId, sourceId });
-  }
-}
-
-InSylvaGatekeeperClient.prototype.baseUrl = null;
-InSylvaGatekeeperClient.prototype.token = null;
-
-export { InSylvaGatekeeperClient };
diff --git a/src/context/InSylvaSourceManager.js b/src/context/InSylvaSourceManager.js
deleted file mode 100644
index a02e89c..0000000
--- a/src/context/InSylvaSourceManager.js
+++ /dev/null
@@ -1,155 +0,0 @@
-class InSylvaSourceManager {
-  async post(method, path, requestContent) {
-    const headers = {
-      'Content-Type': 'application/json',
-      'Access-Control-Allow-Origin': '*',
-      Authorization: `Bearer ${this.token}`,
-    };
-
-    const response = await fetch(`${this.baseUrl}${path}`, {
-      method: method,
-      headers,
-      body: JSON.stringify(requestContent),
-      mode: 'cors',
-    });
-    return await response.json();
-  }
-
-  async createSource(metaUrfms, name, description, kc_id) {
-    const path = `/source`;
-    return await this.post('POST', `${path}`, {
-      metaUrfms,
-      name,
-      description,
-      kc_id,
-    });
-  }
-
-  async sources(kc_id) {
-    const path = '/sources';
-    return await this.post('POST', `${path}`, { kc_id });
-  }
-
-  async indexedSources(kc_id) {
-    const path = '/indexed-sources';
-    return await this.post('POST', `${path}`, { kc_id });
-  }
-
-  async allSource() {
-    const path = '/allSource';
-    return await this.post('GET', `${path}`);
-  }
-
-  async allIndexedSource() {
-    const path = '/allIndexedSource';
-    return await this.post('GET', `${path}`);
-  }
-
-  async addStdField(
-    category,
-    field_name,
-    definition_and_comment,
-    obligation_or_condition,
-    field_type,
-    cardinality,
-    values,
-    isPublic,
-    isOptional
-  ) {
-    const path = `/addStdField`;
-    return await this.post('POST', `${path}`, {
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional,
-    });
-  }
-
-  async addAddtlField(
-    category,
-    field_name,
-    definition_and_comment,
-    obligation_or_condition,
-    field_type,
-    cardinality,
-    values,
-    isPublic,
-    isOptional
-  ) {
-    const path = `/addAddtlField`;
-    return await this.post('POST', `${path}`, {
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional,
-    });
-  }
-
-  async updateStdField(
-    category,
-    field_name,
-    definition_and_comment,
-    obligation_or_condition,
-    field_type,
-    cardinality,
-    values,
-    isPublic,
-    isOptional
-  ) {
-    const path = `/updateStdField`;
-    return await this.post('POST', `${path}`, {
-      category,
-      field_name,
-      definition_and_comment,
-      obligation_or_condition,
-      field_type,
-      cardinality,
-      values,
-      isPublic,
-      isOptional,
-    });
-  }
-
-  async updateSource(kc_id, source_id) {
-    const path = '/update_source';
-    return await this.post('POST', `${path}`, { kc_id, source_id });
-  }
-
-  async publicFields() {
-    const path = `/stdFields`;
-    return this.post('GET', `${path}`);
-  }
-  async privateFields() {
-    const path = `/privateFieldList`;
-    return this.post('GET', `${path}`);
-  }
-
-  async truncateStdField() {
-    const path = `/stdFields/truncate`;
-    return this.post('DELETE', `${path}`);
-  }
-
-  async deleteSource(sourceId, kc_id) {
-    const path = `/source/delete`;
-    return this.post('POST', `${path}`, { sourceId, kc_id });
-  }
-
-  async mergeAndSendSource({ kc_id, name, description, sources }) {
-    const path = `/source/merge-and-send`;
-    return this.post('POST', `${path}`, { kc_id, name, description, sources });
-  }
-}
-
-InSylvaSourceManager.prototype.baseUrl = null;
-InSylvaSourceManager.prototype.token = null;
-export { InSylvaSourceManager };
diff --git a/src/context/KeycloakClient.js b/src/context/KeycloakClient.js
deleted file mode 100644
index 1dcd055..0000000
--- a/src/context/KeycloakClient.js
+++ /dev/null
@@ -1,84 +0,0 @@
-class KeycloakClient {
-  async post(path, requestContent) {
-    const headers = {
-      'Content-Type': 'application/x-www-form-urlencoded',
-      // "Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
-      // "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
-    };
-    let formBody = [];
-    for (const property in requestContent) {
-      const encodedKey = encodeURIComponent(property);
-      const encodedValue = encodeURIComponent(requestContent[property]);
-      formBody.push(encodedKey + '=' + encodedValue);
-    }
-    formBody = formBody.join('&');
-
-    const response = await fetch(`${this.baseUrl}${path}`, {
-      method: 'POST',
-      headers,
-      body: formBody,
-      mode: 'cors',
-    });
-    if (response.ok === true) {
-      // ok
-    } else {
-      // throw new Error(response.status);
-      return await response.json();
-    }
-    if (response.statusText === 'No Content') {
-      // ok
-    } else {
-      return await response.json();
-    }
-  }
-
-  async login({
-    realm = this.realm,
-    client_id = this.client_id,
-    username,
-    password,
-    grant_type = this.grant_type,
-  }) {
-    const path = `/auth/realms/${realm}/protocol/openid-connect/token`;
-    const token = await this.post(`${path}`, {
-      client_id,
-      username,
-      password,
-      grant_type,
-    });
-    return { token };
-  }
-
-  async refreshToken({
-    realm = this.realm,
-    client_id = this.client_id,
-    // client_secret : 'optional depending on the type of client',
-    grant_type = 'refresh_token',
-    refresh_token,
-  }) {
-    const path = `/auth/realms/${realm}/protocol/openid-connect/token`;
-    const token = await this.post(`${path}`, {
-      client_id,
-      grant_type,
-      refresh_token,
-    });
-    return { token };
-  }
-
-  async logout({ realm = this.realm, client_id = this.client_id }) {
-    const refresh_token = sessionStorage.getItem('refresh_token');
-    const path = `/auth/realms/${realm}/protocol/openid-connect/logout`;
-    if (refresh_token) {
-      await this.post(`${path}`, {
-        client_id,
-        refresh_token,
-      });
-    }
-  }
-}
-
-KeycloakClient.prototype.baseUrl = null;
-KeycloakClient.prototype.client_id = null;
-KeycloakClient.prototype.grant_type = null;
-KeycloakClient.prototype.realm = null;
-export { KeycloakClient };
diff --git a/src/context/UserContext.js b/src/context/UserContext.js
deleted file mode 100644
index 5c209e8..0000000
--- a/src/context/UserContext.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import React from 'react';
-import { KeycloakClient } from './KeycloakClient';
-import { InSylvaGatekeeperClient } from './InSylvaGatekeeperClient';
-import { getGatekeeperBaseUrl, getLoginUrl, redirect } from '../utils.js';
-
-const UserStateContext = React.createContext();
-const UserDispatchContext = React.createContext();
-
-const kcClient = new KeycloakClient();
-kcClient.baseUrl = process.env.REACT_APP_IN_SYLVA_KEYCLOAK_PORT
-  ? `${process.env.REACT_APP_IN_SYLVA_KEYCLOAK_HOST}:${process.env.REACT_APP_IN_SYLVA_KEYCLOAK_PORT}`
-  : `${window._env_.REACT_APP_IN_SYLVA_KEYCLOAK_HOST}`;
-kcClient.realm = process.env.REACT_APP_IN_SYLVA_KEYCLOAK_PORT
-  ? `${process.env.REACT_APP_IN_SYLVA_REALM}`
-  : `${window._env_.REACT_APP_IN_SYLVA_REALM}`;
-kcClient.client_id = process.env.REACT_APP_IN_SYLVA_KEYCLOAK_PORT
-  ? `${process.env.REACT_APP_IN_SYLVA_CLIENT_ID}`
-  : `${window._env_.REACT_APP_IN_SYLVA_CLIENT_ID}`;
-kcClient.grant_type = process.env.REACT_APP_IN_SYLVA_KEYCLOAK_PORT
-  ? `${process.env.REACT_APP_IN_SYLVA_GRANT_TYPE}`
-  : `${window._env_.REACT_APP_IN_SYLVA_GRANT_TYPE}`;
-
-const igClient = new InSylvaGatekeeperClient();
-igClient.baseUrl = getGatekeeperBaseUrl();
-
-function userReducer(state, action) {
-  switch (action.type) {
-    case 'LOGIN_SUCCESS':
-      return { ...state, isAuthenticated: true };
-    case 'SIGN_OUT_SUCCESS':
-      return { ...state, isAuthenticated: false };
-    case 'LOGIN_FAILURE':
-      return { ...state, isAuthenticated: false };
-    case 'USER_CREATED':
-      return { ...state };
-    default: {
-      throw new Error(`Unhandled action type: ${action.type} `);
-    }
-  }
-}
-
-function UserProvider({ children }) {
-  const [state, dispatch] = React.useReducer(userReducer, {
-    isAuthenticated: !!sessionStorage.getItem('access_token'),
-  });
-
-  return (
-    <UserStateContext.Provider value={state}>
-      <UserDispatchContext.Provider value={dispatch}>
-        {children}
-      </UserDispatchContext.Provider>
-    </UserStateContext.Provider>
-  );
-}
-
-function useUserState() {
-  const context = React.useContext(UserStateContext);
-  if (context === undefined) {
-    throw new Error('useUserState must be used within a UserProvider');
-  }
-  return context;
-}
-
-function useUserDispatch() {
-  const context = React.useContext(UserDispatchContext);
-  if (context === undefined) {
-    throw new Error('useUserDispatch must be used within a UserProvider');
-  }
-  return context;
-}
-
-async function checkUserLogin(userId, accessToken, refreshToken, roleId) {
-  if (!!userId && !!accessToken && !!refreshToken && !!roleId) {
-    sessionStorage.setItem('userId', userId);
-    sessionStorage.setItem('access_token', accessToken);
-    sessionStorage.setItem('refresh_token', refreshToken);
-    sessionStorage.setItem('roleId', roleId);
-    //To Do:
-    // Load the users histories from UserHistory(userId) endpoint
-    // Load the users result filters from Result_Filter(userId) endpoints
-    // Load the users policies from Policies(userId) endpoint
-    if (!sessionStorage.getItem('token_refresh_time')) {
-      sessionStorage.setItem('token_refresh_time', Date.now());
-    }
-  } else {
-    console.error('users not logged in');
-  }
-}
-
-async function signOut(dispatch) {
-  await kcClient.logout({});
-  dispatch({ type: 'SIGN_OUT_SUCCESS' });
-  sessionStorage.removeItem('access_token');
-  sessionStorage.removeItem('refresh_token');
-  sessionStorage.removeItem('portal');
-  sessionStorage.removeItem('userId');
-  sessionStorage.removeItem('roleId');
-  redirect(getLoginUrl() + '?requestType=portal');
-}
-
-export { UserProvider, useUserState, useUserDispatch, signOut, checkUserLogin };
diff --git a/src/images/logo.png b/src/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..4fabf38732fa03638d007d456bf3b3dffab5f3ea
GIT binary patch
literal 23893
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
MmJzsK<9W>g0hikdyZ`_I

literal 0
HcmV?d00001

diff --git a/src/images/mongo_logo.svg b/src/images/mongo_logo.svg
new file mode 100644
index 0000000..65c4a12
--- /dev/null
+++ b/src/images/mongo_logo.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
+   <circle cx="512" cy="512" r="512" style="fill:#13aa52"/>
+   <path d="M648.86 449.44c-32.34-142.73-108.77-189.66-117-207.59-9-12.65-18.12-35.15-18.12-35.15-.15-.38-.39-1.05-.67-1.7-.93 12.65-1.41 17.53-13.37 30.29-18.52 14.48-113.54 94.21-121.27 256.37-7.21 151.24 109.25 241.36 125 252.85l1.79 1.27v-.11c.1.76 5 36 8.44 73.34H526a726.68 726.68 0 0 1 13-78.53l1-.65a204.48 204.48 0 0 0 20.11-16.45l.72-.65c33.48-30.93 93.67-102.47 93.08-216.53a347.07 347.07 0 0 0-5.05-56.76zM512.35 659.12s0-212.12 7-212.08c5.46 0 12.53 273.61 12.53 273.61-9.72-1.17-19.53-45.03-19.53-61.53z" style="fill:#fff"/>
+</svg>
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index c7ada2c..3d4a198 100755
--- a/src/index.js
+++ b/src/index.js
@@ -6,36 +6,26 @@ import Themes from './themes';
 import '@elastic/eui/dist/eui_theme_light.css';
 import App from './components/App';
 import { LayoutProvider } from './context/LayoutContext';
-import { UserProvider, checkUserLogin } from './context/UserContext';
-import { getLoginUrl, getUrlParam, redirect } from './utils.js';
+import { AuthProvider } from 'react-oidc-context';
+import { userManager } from './services/GatekeeperService';
 
-const userId = getUrlParam('kcId', '');
-const accessToken = getUrlParam('accessToken', '');
-const roleId = getUrlParam('roleId', '');
-
-let refreshToken = getUrlParam('refreshToken', '');
-if (refreshToken.includes('#/app/portal')) {
-  refreshToken = refreshToken.substring(0, refreshToken.indexOf('#'));
-}
-
-checkUserLogin(userId, accessToken, refreshToken, roleId);
-
-//To-Do
-// * delete previous tokens from session storage
-// * refresh tokens
-
-if (sessionStorage.getItem('access_token')) {
-  ReactDOM.render(
+ReactDOM.render(
+  <AuthProvider
+    userManager={userManager}
+    onSigninCallback={() => {
+      window.history.replaceState(
+        {},
+        document.title,
+        window.location.pathname + '#/home'
+      );
+    }}
+  >
     <LayoutProvider>
-      <UserProvider>
-        <ThemeProvider theme={Themes.default}>
-          <CssBaseline />
-          <App userId={userId} accessToken={accessToken} refreshToken={refreshToken} />
-        </ThemeProvider>
-      </UserProvider>
-    </LayoutProvider>,
-    document.getElementById('root')
-  );
-} else {
-  redirect(getLoginUrl() + '?requestType=portal');
-}
+      <ThemeProvider theme={Themes.default}>
+        <CssBaseline />
+        <App />
+      </ThemeProvider>
+    </LayoutProvider>
+  </AuthProvider>,
+  document.getElementById('root')
+);
diff --git a/src/pages/dashboard/Dashboard.js b/src/pages/dashboard/Dashboard.js
index 1932fe6..5807df6 100644
--- a/src/pages/dashboard/Dashboard.js
+++ b/src/pages/dashboard/Dashboard.js
@@ -2,6 +2,7 @@ import React from 'react';
 import { Grid, LinearProgress } from '@material-ui/core';
 import { useTheme } from '@material-ui/styles';
 import keycloakLogo from '../../images/Keycloak_Logo.svg';
+import mongoLogo from '../../images/mongo_logo.svg';
 import {
   ResponsiveContainer,
   AreaChart,
@@ -70,6 +71,13 @@ urlMaps.set(
 export default function Dashboard() {
   const classes = useStyles();
   const theme = useTheme();
+  const {
+    REACT_APP_KIBANA_URL,
+    REACT_APP_PGADMIN_URL,
+    REACT_APP_KEYCLOAK_URL,
+    REACT_APP_PORTAINER_URL,
+    REACT_APP_MONGO_EXPRESS_URL,
+  } = process.env;
 
   return (
     <>
@@ -83,9 +91,8 @@ export default function Dashboard() {
               <div>
                 <EuiButton
                   aria-label="Go to Kibana"
-                  onClick={() => {
-                    window.open(urlMaps.get('kibana'), '_blank');
-                  }}
+                  href={`${REACT_APP_KIBANA_URL}`}
+                  target="_blank"
                 >
                   Go for it
                 </EuiButton>
@@ -96,16 +103,15 @@ export default function Dashboard() {
         </EuiFlexItem>
         <EuiFlexItem>
           <EuiCard
-            icon={<EuiIcon size="xxl" type="logoPostgres" />}
-            title="PgAdmin"
-            description="Access to Postgresql"
+            icon={<EuiIcon size="xxl" type={mongoLogo} />}
+            title="MongoDB"
+            description="Access to MongoDB"
             footer={
               <div>
                 <EuiButton
-                  aria-label="Go to Postgresql"
-                  onClick={() => {
-                    window.open(urlMaps.get('postgresql'), '_blank');
-                  }}
+                  aria-label="Go to MongoDB"
+                  href={`${REACT_APP_MONGO_EXPRESS_URL}`}
+                  target="_blank"
                 >
                   Go for it
                 </EuiButton>
@@ -116,36 +122,15 @@ export default function Dashboard() {
         </EuiFlexItem>
         <EuiFlexItem>
           <EuiCard
-            icon={<EuiIcon size="xxl" type="logoMongodb" />}
-            title="MongoDb"
-            description="Access to MongoDb"
-            footer={
-              <div>
-                <EuiButton
-                  aria-label="Go to MongoDb"
-                  onClick={() => {
-                    window.open(urlMaps.get('mongoDb'), '_blank');
-                  }}
-                >
-                  Go for it
-                </EuiButton>
-                <EuiSpacer size="xs" />
-              </div>
-            }
-          />
-        </EuiFlexItem>
-        <EuiFlexItem>
-          <EuiCard
-            icon={<EuiIcon size="xxl" type="logoElastic" />}
-            title="Elasticsearch"
-            description="Access to Elasticsearch"
+            icon={<EuiIcon size="xxl" type="logoPostgres" />}
+            title="PgAdmin"
+            description="Access to PgAdmin"
             footer={
               <div>
                 <EuiButton
-                  aria-label="Go to Elasticsearch"
-                  onClick={() => {
-                    window.open(urlMaps.get('elasticsearch'), '_blank');
-                  }}
+                  aria-label="Go to PgAdmin"
+                  href={`${REACT_APP_PGADMIN_URL}`}
+                  target="_blank"
                 >
                   Go for it
                 </EuiButton>
@@ -163,9 +148,8 @@ export default function Dashboard() {
               <div>
                 <EuiButton
                   aria-label="Go to Keycloak"
-                  onClick={() => {
-                    window.open(urlMaps.get('keycloak'), '_blank');
-                  }}
+                  href={`${REACT_APP_KEYCLOAK_URL}`}
+                  target="_blank"
                 >
                   Go for it
                 </EuiButton>
@@ -183,9 +167,8 @@ export default function Dashboard() {
               <div>
                 <EuiButton
                   aria-label="Go to Portainer"
-                  onClick={() => {
-                    window.open(urlMaps.get('portainer'), '_blank');
-                  }}
+                  href={`${REACT_APP_PORTAINER_URL}`}
+                  target="_blank"
                 >
                   Go for it
                 </EuiButton>
diff --git a/src/pages/error/403.js b/src/pages/error/403.js
new file mode 100644
index 0000000..1cace73
--- /dev/null
+++ b/src/pages/error/403.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import { Grid, Paper, Typography, Button } from '@material-ui/core';
+import classnames from 'classnames';
+import useStyles from './styles';
+import logo from './logo.png';
+
+export default function Error403() {
+  const classes = useStyles();
+
+  return (
+    <Grid container className={classes.container}>
+      <div className={classes.logotype}>
+        <img className={classes.logotypeIcon} src={logo} alt="logo" />
+        <Typography variant="h3" color="white" className={classes.logotypeText}>
+          In-Sylva Project
+        </Typography>
+      </div>
+      <Paper classes={{ root: classes.paperRoot }}>
+        <Typography
+          variant="h1"
+          color="primary"
+          className={classnames(classes.textRow, classes.errorCode)}
+        >
+          403
+        </Typography>
+        <Typography variant="h5" color="primary" className={classes.textRow}>
+          Forbidden
+        </Typography>
+        <Typography variant="h5" color="primary" className={classes.textRow}>
+          Oops. Looks like you don't have the right permissions to access this page
+        </Typography>
+        <Button
+          href="#/home"
+          variant="contained"
+          color="primary"
+          size="large"
+          className={classes.backButton}
+        >
+          Back to Home
+        </Button>
+      </Paper>
+    </Grid>
+  );
+}
diff --git a/src/pages/error/Error.js b/src/pages/error/404.js
similarity index 77%
rename from src/pages/error/Error.js
rename to src/pages/error/404.js
index e466863..ccf5ebe 100644
--- a/src/pages/error/Error.js
+++ b/src/pages/error/404.js
@@ -1,13 +1,11 @@
 import React from 'react';
 import { Grid, Paper, Typography, Button } from '@material-ui/core';
-import { Link } from 'react-router-dom';
 import classnames from 'classnames';
 import useStyles from './styles';
 import logo from './logo.png';
 
-export default function Error() {
+export default function Error404() {
   const classes = useStyles();
-
   return (
     <Grid container className={classes.container}>
       <div className={classes.logotype}>
@@ -25,21 +23,15 @@ export default function Error() {
           404
         </Typography>
         <Typography variant="h5" color="primary" className={classes.textRow}>
-          Oops. Looks like the page you're looking for no longer exists
+          Not Found
         </Typography>
-        <Typography
-          variant="h6"
-          color="text"
-          colorBrightness="secondary"
-          className={classnames(classes.textRow, classes.safetyText)}
-        >
-          But we're here to bring you back to safety
+        <Typography variant="h5" color="primary" className={classes.textRow}>
+          Oops. Looks like the page you're looking for no longer exists
         </Typography>
         <Button
+          href="#/home"
           variant="contained"
           color="primary"
-          component={Link}
-          to="/"
           size="large"
           className={classes.backButton}
         >
diff --git a/src/pages/fields/Fields.js b/src/pages/fields/Fields.js
index 1ec424c..46f766a 100644
--- a/src/pages/fields/Fields.js
+++ b/src/pages/fields/Fields.js
@@ -1,5 +1,4 @@
-import React, { useState, useCallback, useEffect, memo, useRef } from 'react';
-import store from '../../store/index';
+import React, { useState, useCallback, useEffect, memo } from 'react';
 import {
   EuiForm,
   EuiPageContent,
@@ -16,6 +15,11 @@ import {
 } from '@elastic/eui';
 import { ShowAlert } from '../../components/Common';
 import Papa from 'papaparse';
+import {
+  getPublicFields,
+  deleteAllStdFields,
+  createStdField,
+} from '../../services/GatekeeperService';
 
 const renderFiles = (files) => {
   if (files && files.length > 0) {
@@ -33,7 +37,7 @@ const renderFiles = (files) => {
   }
 };
 
-const NewFieldsForm = memo(({ files, globalState, onFilePickerChange, onSaveField }) => {
+const NewFieldsForm = memo(({ files, onFilePickerChange, onSaveField }) => {
   return (
     <>
       <EuiForm component="form">
@@ -56,7 +60,7 @@ const NewFieldsForm = memo(({ files, globalState, onFilePickerChange, onSaveFiel
         </EuiFormRow>
         <EuiFormRow label="">
           {
-            <EuiButton fill onClick={onSaveField} isLoading={globalState.isLoading}>
+            <EuiButton fill onClick={onSaveField}>
               Load
             </EuiButton>
           }
@@ -66,69 +70,47 @@ const NewFieldsForm = memo(({ files, globalState, onFilePickerChange, onSaveFiel
   );
 });
 
-const StdFields = memo(
-  ({
-    stdFields,
-    stdFieldColumns,
-    tableref,
-    pagination,
-    sorting,
-    onTableChange,
-    onSelection,
-    search,
-    isLoading,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFormRow label="Uploaded standard fields" fullWidth>
-            <EuiInMemoryTable
-              // ref={tableref}
-              // itemId="id"
-              // isSelectable={true}
-              items={stdFields}
-              loading={isLoading}
-              columns={stdFieldColumns}
-              search={search}
-              pagination={true}
-              sorting={true}
-              // onChange={onTableChange}
-              // rowheader={"field_name"}
-              // selection={onSelection}
-            />
-          </EuiFormRow>
-        </EuiForm>
-      </>
-    );
-  }
-);
+const StdFields = memo(({ stdFields, stdFieldColumns }) => {
+  return (
+    <>
+      <EuiForm component="form">
+        <EuiFormRow label="Uploaded standard fields" fullWidth>
+          <EuiInMemoryTable
+            items={stdFields}
+            columns={stdFieldColumns}
+            search={{
+              box: {
+                incremental: true,
+              },
+            }}
+            pagination={true}
+            sorting={true}
+          />
+        </EuiFormRow>
+      </EuiForm>
+    </>
+  );
+});
 let debounceTimeoutId;
 let requestTimeoutId;
 
 const Fields = (props) => {
-  const [globalState, globalActions] = store();
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
   const [open, setOpen] = useState(false);
   const [alertMessage, setAlertMessage] = useState('');
   const [severity, setSeverity] = useState('info');
   const [files, setFiles] = useState();
-  const [fields, setFields] = useState([]);
+  const [loadedFields, setLoadedFields] = useState([]);
   const [stdFields, setStdFields] = useState([]);
-  const [pageIndex, setPageIndex] = useState(0);
-  const [pageSize, setPageSize] = useState(5);
-  const [sortDirection, setSortDirection] = useState('asc');
-  const [sortField, setSortField] = useState('field_name');
-  const [totalItemCount, setTotalItemCount] = useState(0);
-  const tableref = useRef();
-  const [isLoading, setIsLoading] = useState(false);
+  const [filteredFields, setFilteredFields] = useState([]);
 
   const loadStdFields = useCallback(async () => {
-    const fields = await globalActions.source.publicFields();
+    const fields = await getPublicFields();
     if (fields) {
-      setStdFields((prevFields) => [...prevFields, ...fields]);
-      setTotalItemCount(typeof fields === typeof undefined ? 0 : fields.length);
+      setStdFields(fields);
+      setFilteredFields(fields);
     }
-  }, [globalActions.source]);
+  }, []);
 
   useEffect(() => {
     // clean up controller
@@ -138,69 +120,25 @@ const Fields = (props) => {
     }
     // cancel subscription to useEffect
     return () => (isSubscribed = false);
-  }, [totalItemCount, loadStdFields]);
+  }, [loadStdFields]);
 
   const onQueryChange = ({ query }) => {
     clearTimeout(debounceTimeoutId);
-    clearTimeout(requestTimeoutId);
-
     debounceTimeoutId = setTimeout(() => {
-      setIsLoading(true);
-      requestTimeoutId = setTimeout(() => {
-        const items = stdFields.filter((field) => {
-          const normalizedFieldName =
-            `${field.field_name} ${field.Definition_and_comment}`.toLowerCase();
-          const normalizedQuery = query.text.toLowerCase();
-          return normalizedFieldName.indexOf(normalizedQuery) !== -1;
-        });
-        if (query.text !== '') {
-          setIsLoading(false);
-          setStdFields(items);
-        } else {
-          loadStdFields();
-        }
-      }, 1000);
+      const items = stdFields.filter((field) => {
+        const normalizedFieldName =
+          `${field.field_name} ${field.Definition_and_comment}`.toLowerCase();
+        const normalizedQuery = query.text.toLowerCase();
+        return normalizedFieldName.indexOf(normalizedQuery) !== -1;
+      });
+      if (query.text !== '') {
+        setFilteredFields(items);
+      } else {
+        setFilteredFields([]);
+      }
     }, 300);
   };
 
-  const search = {
-    onChange: onQueryChange,
-    box: {
-      incremental: true,
-    },
-  };
-
-  /*
-    const onSelection = {
-        selectable: source => !source.is_send,
-        onSelectionChange: onSelectionChange,
-        initialSelected: unsentSources,
-    }; */
-
-  const onTableChange = ({ page = {}, sort = {} }) => {
-    const { index: pageIndex, size: pageSize } = page;
-    const { field: sortField, direction: sortDirection } = sort;
-
-    setPageIndex(pageIndex);
-    setPageSize(pageSize);
-    setSortField(sortField);
-    setSortDirection(sortDirection);
-  };
-
-  const pagination = {
-    pageIndex: pageIndex,
-    pageSize: pageSize,
-    totalItemCount: totalItemCount,
-    pageSizeOptions: [3, 5, 8],
-  };
-
-  const sorting = {
-    sort: {
-      field: sortField,
-      direction: sortDirection,
-    },
-  };
-
   const onFilePickerChange = async (files) => {
     setFiles(files);
     await handleSelectedFile(files);
@@ -209,8 +147,8 @@ const Fields = (props) => {
   const handleSelectedFile = async (files) => {
     for (const file of files) {
       const reader = new FileReader();
-      await reader.readAsText(file);
       reader.onload = () => handleData(reader.result);
+      reader.readAsText(file);
     }
   };
 
@@ -230,38 +168,70 @@ const Fields = (props) => {
       });
 
       result.data.forEach((item) => {
+        // lowercase the key
+        Object.keys(item).forEach((key) => {
+          const lowercasedKey = key.toLowerCase();
+          if (key !== lowercasedKey) {
+            item[lowercasedKey] = item[key];
+            delete item[key];
+          }
+        });
         rows.push(item);
       });
 
       if (columns && rows) {
-        // (preColumns => ([...preColumns, ...columns]))
-        setFields((preRows) => [...preRows, ...rows]);
+        setLoadedFields((preRows) => [...preRows, ...rows]);
       }
     }
   };
 
   const onSaveField = async () => {
-    if (fields) {
-      await globalActions.source.truncateStdField();
+    if (loadedFields) {
+      await deleteAllStdFields();
+      try {
+        for (const field of loadedFields) {
+          const {
+            cardinality,
+            category,
+            definition_and_comment,
+            field_name,
+            field_type,
+            isoptional,
+            is_optional,
+            ispublic,
+            is_public,
+            obligation_or_condition,
+            values,
+            list_url,
+            default_display_fields
+          } = field;
 
-      await fields.forEach((item) => {
-        globalActions.source.createStdField(
-          item.Category,
-          item.Field_name,
-          item.Definition_and_comment,
-          item.Obligation_or_condition,
-          item.Field_type,
-          item.Cardinality,
-          item.Values,
-          item.is_public,
-          false
-        );
-      });
+          console.log("fields: ", field);
+          const isOptional = isoptional || is_optional;
+          const isPublic = ispublic || is_public;
+          const response = await createStdField(
+            cardinality,
+            category,
+            definition_and_comment,
+            field_name,
+            field_type,
+            isOptional?.toString().toLowerCase() === 'true',
+            isPublic?.toString().toLowerCase() === 'true',
+            obligation_or_condition,
+            values,
+              list_url,
+              default_display_fields
+          );
+        }
 
-      setOpen(true);
-      setAlertMessage('Standard fields added.');
-      setSeverity('success');
-      loadStdFields();
+        // Reload fields after processing
+        loadStdFields();
+      } catch (error) {
+        console.error('Unexpected error during field saving:', error);
+        setOpen(true);
+        setAlertMessage('An unexpected error occurred.');
+        setSeverity('error');
+      }
     }
   };
 
@@ -285,6 +255,18 @@ const Fields = (props) => {
       field: 'Obligation_or_condition',
       name: 'Obligation or condition',
     },
+    {
+      field: 'cardinality',
+      name: 'Cardinality',
+    },
+    {
+      field: 'default_display_fields',
+      name: 'Default display fields',
+    },
+    {
+      field: 'list_url',
+      name: 'List URL',
+    },
     {
       field: 'values',
       name: 'Values',
@@ -303,7 +285,6 @@ const Fields = (props) => {
           <br />
           <NewFieldsForm
             files={files}
-            globalState={globalState}
             onFilePickerChange={onFilePickerChange}
             onSaveField={onSaveField}
           />
@@ -316,16 +297,7 @@ const Fields = (props) => {
       content: (
         <>
           <br />
-          <StdFields
-            stdFields={stdFields}
-            stdFieldColumns={stdFieldColumns}
-            pagination={pagination}
-            sorting={sorting}
-            tableref={tableref}
-            onTableChange={onTableChange}
-            search={search}
-            loading={isLoading}
-          />
+          <StdFields stdFields={stdFields} stdFieldColumns={stdFieldColumns} />
         </>
       ),
     },
diff --git a/src/pages/groups/Groups.js b/src/pages/groups/Groups.js
index eeb1655..8e4441d 100644
--- a/src/pages/groups/Groups.js
+++ b/src/pages/groups/Groups.js
@@ -1,5 +1,4 @@
 import React, { useState, Fragment, useEffect, memo, useCallback } from 'react';
-import store from '../../store/index';
 import { ShowAlert } from '../../components/Common';
 import {
   EuiForm,
@@ -19,10 +18,17 @@ import {
   EuiSelectable,
   EuiComboBox,
 } from '@elastic/eui';
+import {
+  createGroup,
+  getGroups,
+  getUsers,
+  deleteGroup,
+  addUserToGroup,
+  removeUserFromGroup,
+} from '../../services/GatekeeperService';
 
 const NewGroupForm = memo(
   ({
-    globalState,
     groupNameValue,
     setGroupNameValue,
     groupDescriptionValue,
@@ -50,7 +56,7 @@ const NewGroupForm = memo(
           </EuiFormRow>
           <EuiSpacer />
           {
-            <EuiButton fill onClick={onSaveGroup} isLoading={globalState.isLoading}>
+            <EuiButton fill onClick={onSaveGroup}>
               Save
             </EuiButton>
           }
@@ -65,7 +71,7 @@ const NewGroupForm = memo(
 );
 
 const GroupAssignment = memo(
-  ({ groups, setGroups, users, setUsers, onGroupAssignment, globalState }) => {
+  ({ groups, setGroups, users, setUsers, onGroupAssignment }) => {
     return (
       <>
         <EuiForm component="form">
@@ -106,12 +112,7 @@ const GroupAssignment = memo(
           </EuiFlexGroup>
           <EuiSpacer />
           {
-            <EuiButton
-              type="submit"
-              onClick={onGroupAssignment}
-              isLoading={globalState.isLoading}
-              fill
-            >
+            <EuiButton type="submit" onClick={onGroupAssignment} fill>
               Save
             </EuiButton>
           }
@@ -135,7 +136,7 @@ const AssignedGroups = memo(
           <EuiFormRow label="Select specific group">
             <EuiComboBox
               placeholder="Select a group"
-              singleSelection={{ asPlainText: true }}
+              singleSelection={true}
               options={groups}
               selectedOptions={selectedGroup}
               onChange={(e) => {
@@ -154,20 +155,22 @@ const AssignedGroups = memo(
 
 const Groups = () => {
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
-  const [globalState, globalActions] = store();
   const [groupNameValue, setGroupNameValue] = useState('');
   const [groupDescriptionValue, setGroupDescriptionValue] = useState('');
   const [groups, setGroups] = useState([]);
+
   const [open, setOpen] = useState(false);
   const [alertMessage, setAlertMessage] = useState('');
   const [severity, setSeverity] = useState('info');
+
   const [users, setUsers] = useState([]);
   const [tblGroups, setTblGroups] = useState([]);
   const [selectedGroup, setSelectedGroup] = useState([]);
   const [groupedUsers, setGroupedUsers] = useState([]);
+  const [refresh, setRefresh] = useState(true);
 
   const loadGroups = useCallback(async () => {
-    const _groups = await globalActions.group.getGroups();
+    const _groups = await getGroups();
     if (_groups) {
       const grouplist = [];
       for (const group of _groups) {
@@ -178,55 +181,62 @@ const Groups = () => {
       }
       setGroups(_groups);
     }
-  }, [globalActions.group]);
+  }, []);
 
   const loadUsers = useCallback(async () => {
-    const _users = await globalActions.user.findUser();
+    const _users = await getUsers();
     const usersList = [];
     if (_users) {
       for (const user of _users) {
-        usersList.push({ value: user.id, label: user.username });
+        usersList.push({ value: user.id, label: user.email, sub: user.kc_id });
       }
       if (usersList) {
         setUsers(usersList);
       }
     }
-  }, [globalActions.user]);
+  }, []);
 
   useEffect(() => {
-    let isSubscribed = true;
-    if (isSubscribed) {
+    if (refresh) {
+      setRefresh(false);
       loadGroups();
       loadUsers();
+      onSelectedGroup([]);
     }
-    return () => (isSubscribed = false);
-  }, [loadGroups, loadUsers]);
+  }, [loadGroups, loadUsers, refresh, setRefresh]);
 
   const onDeleteGroup = async (group) => {
     if (group) {
-      await globalActions.group.deleteGroup(group.id);
+      const result = await deleteGroup(group.id);
+      if (result) {
+        setAlertMessage('Group has been deleted.');
+        setSeverity('success');
+        setRefresh(true);
+      } else {
+        setAlertMessage(`Error: ${result.error}`);
+        setSeverity('error');
+      }
+      setOpen(true);
     }
-    loadGroups();
   };
 
   const onSaveGroup = async () => {
-    if (groupNameValue && sessionStorage.getItem('userId')) {
-      await globalActions.group.createGroup(
-        groupNameValue,
-        groupDescriptionValue,
-        sessionStorage.getItem('userId')
-      );
-
-      if (globalState.status === 'SUCCESS') {
-        setOpen(true);
+    if (groupNameValue && groupDescriptionValue) {
+      const result = await createGroup(groupNameValue, groupDescriptionValue);
+      if (result?.id) {
         setAlertMessage('Group has been created.');
         setSeverity('success');
+        setRefresh(true);
+      } else {
+        setAlertMessage(`Error: ${result.error}`);
+        setSeverity('error');
       }
-      await loadGroups();
+      setOpen(true);
     }
   };
 
-  const onGroupAssignment = async () => {
+  const onGroupAssignment = async (e) => {
+    e.preventDefault();
     const checkedGroups = tblGroups.filter((e) => {
       return e.checked === 'on';
     });
@@ -237,30 +247,37 @@ const Groups = () => {
 
     for (const user of checkedUsers) {
       for (const group of checkedGroups) {
-        await globalActions.group.createGroupUser(group.value, user.value);
+        const response = await addUserToGroup(user.sub, group.value);
       }
-    }
-
-    if (globalState.status === 'SUCCESS') {
-      setOpen(true);
-      setAlertMessage('Users-group assignment has been completed.');
-      setSeverity('success');
+      setRefresh(true);
     }
   };
 
   const onRemoveUserFromGroup = async (e) => {
-    await globalActions.group.deleteGroupUser(e.groupid, e.userid);
-    const groupedUsers = await globalActions.group.getGroupUsers(e.groupid);
-    setGroupedUsers(groupedUsers);
+    await removeUserFromGroup(e.sub, e.groupId);
+    onSelectedGroup([]);
+    setRefresh(true);
   };
 
   const onSelectedGroup = async (e) => {
     if (e.length > 0) {
-      const groupedUsers = await globalActions.group.getGroupUsers(e[0].value);
-      setGroupedUsers(groupedUsers);
+      const selectedGroup = groups.filter((group) => {
+        return group.id === e[0].value;
+      });
+      const groupUsers = selectedGroup.map((group) => {
+        return group.users.map((user) => ({
+          email: user.user.email,
+          name: group.name,
+          groupId: group.id,
+          description: group.description,
+          sub: user.user.kc_id,
+        }));
+      });
+      setGroupedUsers(groupUsers.flatMap((x) => x));
       setSelectedGroup(e);
     } else {
-      setSelectedGroup(e);
+      setGroupedUsers([]);
+      setSelectedGroup([]);
     }
   };
 
@@ -271,7 +288,9 @@ const Groups = () => {
       icon: 'trash',
       type: 'icon',
       color: 'danger',
-      onClick: onDeleteGroup,
+      onClick: async (group) => {
+        await onDeleteGroup(group);
+      },
     },
   ];
 
@@ -289,11 +308,11 @@ const Groups = () => {
   const groupColumns = [
     { field: 'name', name: 'Group name' },
     { field: 'description', name: 'Group description' },
-    { name: 'Actions', actions: groupActions },
+    { name: 'Actions', actions: groupActions, truncateText: true },
   ];
 
   const assignedGroupedUserColumns = [
-    { field: 'username', name: 'Username' },
+    { field: 'email', name: 'Email' },
     { field: 'name', name: 'Group name' },
     { field: 'description', name: 'Group description' },
     { name: 'Actions', actions: assignedGroupedUserActions },
@@ -306,7 +325,6 @@ const Groups = () => {
       content: (
         <>
           <NewGroupForm
-            globalState={globalState}
             groupNameValue={groupNameValue}
             setGroupNameValue={setGroupNameValue}
             groupDescriptionValue={groupDescriptionValue}
@@ -329,7 +347,6 @@ const Groups = () => {
             users={users}
             setUsers={setUsers}
             onGroupAssignment={onGroupAssignment}
-            globalState={globalState}
           />
         </>
       ),
diff --git a/src/pages/home/Home.js b/src/pages/home/Home.js
new file mode 100644
index 0000000..76e97bc
--- /dev/null
+++ b/src/pages/home/Home.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import {
+  EuiButton,
+  EuiIcon,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiText,
+  EuiSpacer,
+} from '@elastic/eui';
+import logo from '../../images/logo.png';
+import useStyles from './styles';
+
+export default function Home() {
+  const classes = useStyles();
+  const { REACT_APP_VALIDATOR_URL } = process.env;
+
+  return (
+    <EuiFlexGroup
+      direction="column"
+      justifyContent="center"
+      alignItems="center"
+      style={{ minHeight: 'calc(90vh)', textAlign: 'center' }}
+    >
+      {/* Logo at the top */}
+      <EuiFlexItem grow={false}>
+        <EuiIcon type={logo} size="original" />
+      </EuiFlexItem>
+
+      {/* Main content */}
+      <EuiFlexItem>
+        <div className={classes.heroContainer}>
+          <EuiText>
+            <h1>Welcome to the Portal</h1>
+            <p>
+              This is the central hub for managing users, groups, sources, policies,
+              fields, and relationships between them.
+            </p>
+          </EuiText>
+          <EuiSpacer size="l" />
+          <EuiButton color="primary" size="m" href={`${REACT_APP_VALIDATOR_URL}`} target="_blank">
+            <EuiIcon type="checkInCircleFilled" size="l" />
+            &nbsp; Validate your JSON sources
+          </EuiButton>
+        </div>
+      </EuiFlexItem>
+    </EuiFlexGroup>
+  );
+}
diff --git a/src/pages/home/package.json b/src/pages/home/package.json
new file mode 100644
index 0000000..2ecfad4
--- /dev/null
+++ b/src/pages/home/package.json
@@ -0,0 +1,7 @@
+{
+    "name": "Home",
+    "version": "1.0.0",
+    "private": true,
+    "main": "Home.js"
+  }
+  
\ No newline at end of file
diff --git a/src/pages/home/styles.js b/src/pages/home/styles.js
new file mode 100644
index 0000000..05e123e
--- /dev/null
+++ b/src/pages/home/styles.js
@@ -0,0 +1,25 @@
+import { makeStyles } from '@material-ui/styles';
+
+export default makeStyles((theme) => ({
+  root: {
+    display: 'flex',
+    maxWidth: '100vw',
+    overflowX: 'hidden',
+  },
+  content: {
+    flexGrow: 1,
+    padding: theme.spacing(3),
+    width: `calc(100vw - 240px)`,
+    minHeight: '100vh',
+  },
+  contentShift: {
+    width: `calc(100vw - ${240 + theme.spacing(6)}px)`,
+    transition: theme.transitions.create(['width', 'margin'], {
+      easing: theme.transitions.easing.sharp,
+      duration: theme.transitions.duration.enteringScreen,
+    }),
+  },
+  fakeToolbar: {
+    ...theme.mixins.toolbar,
+  },
+}));
diff --git a/src/pages/policies/AssignedPolicies.js b/src/pages/policies/AssignedPolicies.js
new file mode 100644
index 0000000..53ca15c
--- /dev/null
+++ b/src/pages/policies/AssignedPolicies.js
@@ -0,0 +1,131 @@
+import React, { memo } from 'react';
+import { EuiBasicTable, EuiComboBox, EuiForm, EuiFormRow } from '@elastic/eui';
+
+const AssignedPolicies = memo(
+  ({
+    policies,
+    selectedPolicy,
+    onSelectedPolicy,
+    assignedPolicySources,
+    assignedPolicyFields,
+    assignedPolicyGroups,
+    onDeletePolicySource,
+    onDeletePolicyField,
+    onDeletePolicyGroup,
+  }) => {
+    const assignedPolicyColumns = [
+      {
+        field: 'field_name',
+        name: 'Field name',
+        sortable: true,
+      },
+      {
+        field: 'definition_and_comment',
+        name: 'Definition and comment',
+        truncateText: true,
+        mobileOptions: {
+          show: false,
+        },
+      },
+      {
+        field: 'field_type',
+        name: 'Field type',
+      },
+      {
+        name: 'Actions',
+        actions: [
+          {
+            name: 'Delete',
+            description: 'Delete this policies-field',
+            icon: 'trash',
+            type: 'icon',
+            color: 'danger',
+            onClick: async (e) => {
+              await onDeletePolicyField(e);
+            },
+          },
+        ],
+      },
+    ];
+
+    const assignedPolicyGroupColumns = [
+      { field: 'group_name', name: 'Group name' },
+      { field: 'group_description', name: 'Group description' },
+      {
+        name: 'Actions',
+        actions: [
+          {
+            name: 'Delete',
+            description: 'Delete this policies-group',
+            icon: 'trash',
+            type: 'icon',
+            color: 'danger',
+            onClick: async (e) => {
+              await onDeletePolicyGroup(e);
+            },
+          },
+        ],
+      },
+    ];
+
+    const assignedPolicySourceColumns = [
+      {
+        field: 'source_name',
+        name: 'Source name',
+      },
+      {
+        field: 'source_description',
+        name: 'Source description',
+      },
+      {
+        name: 'Actions',
+        actions: [
+          {
+            name: 'Delete',
+            description: 'Delete this policy-source',
+            icon: 'trash',
+            type: 'icon',
+            color: 'danger',
+            onClick: async (e) => {
+              await onDeletePolicySource(e);
+            },
+          },
+        ],
+      },
+    ];
+    return (
+      <>
+        <EuiForm component="form">
+          <EuiFormRow label="Select a specific policy">
+            <EuiComboBox
+              placeholder="Select a policy"
+              singleSelection={true}
+              options={policies}
+              selectedOptions={selectedPolicy}
+              onChange={(e) => {
+                onSelectedPolicy(e);
+              }}
+            />
+          </EuiFormRow>
+          <EuiFormRow label="Assigned sources" fullWidth>
+            <EuiBasicTable
+              items={assignedPolicySources}
+              columns={assignedPolicySourceColumns}
+            />
+          </EuiFormRow>
+          <EuiFormRow label="Assigned standard fields" fullWidth>
+            <EuiBasicTable items={assignedPolicyFields} columns={assignedPolicyColumns} />
+          </EuiFormRow>
+          <EuiFormRow label="Assigned groups" fullWidth>
+            <EuiBasicTable
+              items={assignedPolicyGroups}
+              columns={assignedPolicyGroupColumns}
+            />
+          </EuiFormRow>
+        </EuiForm>
+      </>
+    );
+  }
+);
+
+export default AssignedPolicies;
diff --git a/src/pages/policies/NewPolicyForm.js b/src/pages/policies/NewPolicyForm.js
new file mode 100644
index 0000000..6350ba1
--- /dev/null
+++ b/src/pages/policies/NewPolicyForm.js
@@ -0,0 +1,59 @@
+import React, { memo } from 'react';
+import {
+  EuiForm,
+  EuiFormRow,
+  EuiFieldText,
+  EuiButton,
+  EuiSpacer,
+  EuiBasicTable,
+} from '@elastic/eui';
+
+const NewPolicyForm = memo(
+  ({ policyName, setPolicyName, onSaveNewPolicy, onDeletePolicy, policies }) => {
+    const policyColumns = [
+      {
+        field: 'policyname',
+        name: 'Policy name',
+      },
+      {
+        field: 'sourcename',
+        name: 'Source name',
+      },
+      {
+        name: 'Actions',
+        actions: [
+          {
+            name: 'Delete',
+            description: 'Delete this policy',
+            icon: 'trash',
+            type: 'icon',
+            color: 'danger',
+            onClick: onDeletePolicy,
+          },
+        ],
+      },
+    ];
+    return (
+      <>
+        <EuiForm component="form">
+          <EuiFormRow label="Policy name">
+            <EuiFieldText
+              value={policyName}
+              onChange={(e) => setPolicyName(e.target.value)}
+            />
+          </EuiFormRow>
+          <EuiSpacer />
+          <EuiButton type="submit" onClick={onSaveNewPolicy} fill>
+            Save
+          </EuiButton>
+          <EuiSpacer />
+          <EuiFormRow label="" fullWidth>
+            <EuiBasicTable items={policies} rowheader="Name" columns={policyColumns} />
+          </EuiFormRow>
+        </EuiForm>
+      </>
+    );
+  }
+);
+
+export default NewPolicyForm;
diff --git a/src/pages/policies/Policies.js b/src/pages/policies/Policies.js
index ab3c622..e53c0d5 100644
--- a/src/pages/policies/Policies.js
+++ b/src/pages/policies/Policies.js
@@ -1,5 +1,4 @@
-import React, { useState, Fragment, useCallback, useEffect, memo } from 'react';
-import store from '../../store/index';
+import React, { useState, useCallback, useEffect } from 'react';
 import {
   EuiForm,
   EuiPageContent,
@@ -8,306 +7,45 @@ import {
   EuiTitle,
   EuiPageContentBody,
   EuiTabbedContent,
-  EuiFormRow,
-  EuiFieldText,
-  EuiFlexGroup,
-  EuiFlexItem,
-  EuiSpacer,
-  EuiButton,
-  EuiBasicTable,
-  EuiSelectable,
-  EuiComboBox,
 } from '@elastic/eui';
+import PolicyAssignment from './PolicyAssignment';
+import PolicyGroupAssignment from './PolicyGroupAssignment';
+import PolicySourceAssignment from './PolicySourceAssignment';
+import NewPolicyForm from './NewPolicyForm';
+import AssignedPolicies from './AssignedPolicies';
 import { ShowAlert } from '../../components/Common';
-
-const NewPolicyForm = memo(
-  ({
-    globalState,
-    policyName,
-    setPolicyName,
-    sources,
-    isSwitchChecked,
-    onSwitchChange,
-    selectedSource,
-    setSelectedSource,
-    onSaveNewPolicy,
-    policies,
-    policyColumns,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFormRow label="Policy name">
-            <EuiFieldText
-              value={policyName}
-              onChange={(e) => setPolicyName(e.target.value)}
-            />
-          </EuiFormRow>
-          <EuiSpacer />
-          <EuiButton
-            type="submit"
-            onClick={onSaveNewPolicy}
-            isLoading={globalState.isLoading}
-            fill
-          >
-            Save
-          </EuiButton>
-          <EuiSpacer />
-          <EuiFormRow label="" fullWidth>
-            <EuiBasicTable items={policies} rowheader="Name" columns={policyColumns} />
-          </EuiFormRow>
-        </EuiForm>
-      </>
-    );
-  }
-);
-
-const PolicyAssignment = memo(
-  ({
-    globalState,
-    optPolicies,
-    setOptPolicies,
-    optStdFields,
-    setOptStdFields,
-    onPolicyAssignment,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFlexGroup component="span">
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Policies" fullWidth>
-                <EuiSelectable
-                  searchable
-                  singleSelection={true}
-                  options={optPolicies}
-                  onChange={(newOptions) => setOptPolicies(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Standard fields" fullWidth>
-                <EuiSelectable
-                  searchable
-                  options={optStdFields}
-                  onChange={(newOptions) => setOptStdFields(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-          </EuiFlexGroup>
-          <EuiSpacer />
-          <EuiButton
-            type="submit"
-            onClick={onPolicyAssignment}
-            isLoading={globalState.isLoading}
-            fill
-          >
-            Save
-          </EuiButton>
-        </EuiForm>
-      </>
-    );
-  }
-);
-
-const PolicyGroupAssignment = memo(
-  ({
-    globalState,
-    optPolicies,
-    setOptPolicies,
-    optGroups,
-    setOPtGroups,
-    onPolicyGroupAssignment,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFlexGroup component="span">
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Policies" fullWidth>
-                <EuiSelectable
-                  searchable
-                  singleSelection={true}
-                  options={optPolicies}
-                  onChange={(newOptions) => setOptPolicies(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Groups" fullWidth>
-                <EuiSelectable
-                  searchable
-                  options={optGroups}
-                  onChange={(newOptions) => setOPtGroups(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-          </EuiFlexGroup>
-          <EuiSpacer />
-          <EuiButton
-            type="submit"
-            onClick={onPolicyGroupAssignment}
-            isLoading={globalState.isLoading}
-            fill
-          >
-            Save
-          </EuiButton>
-        </EuiForm>
-      </>
-    );
-  }
-);
-
-const PolicySourceAssignment = memo(
-  ({
-    globalState,
-    optPolicies,
-    setOptPolicies,
-    optSources,
-    setOptSources,
-    onPolicySourceAssignment,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFlexGroup component="span">
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Policies" fullWidth>
-                <EuiSelectable
-                  searchable
-                  singleSelection={true}
-                  options={optPolicies}
-                  onChange={(newOptions) => setOptPolicies(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-            <EuiFlexItem component="span">
-              <EuiFormRow label="Sources" fullWidth>
-                <EuiSelectable
-                  searchable
-                  singleSelection={true}
-                  options={optSources}
-                  onChange={(newOptions) => setOptSources(newOptions)}
-                >
-                  {(list, search) => (
-                    <Fragment>
-                      {search}
-                      {list}
-                    </Fragment>
-                  )}
-                </EuiSelectable>
-              </EuiFormRow>
-            </EuiFlexItem>
-          </EuiFlexGroup>
-          <EuiSpacer />
-          <EuiButton
-            type="submit"
-            onClick={onPolicySourceAssignment}
-            isLoading={globalState.isLoading}
-            fill
-          >
-            Save
-          </EuiButton>
-        </EuiForm>
-      </>
-    );
-  }
-);
-
-const AssignedPolicies = memo(
-  ({
-    policies,
-    selectedPolicy,
-    fields,
-    assignedPolicyColumns,
-    getRowProps,
-    getCellProps,
-    onSelectedPolicy,
-    assignedPolicyGroups,
-    assignedPolicyGroupColumns,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFormRow label="Select a specific policy">
-            <EuiComboBox
-              placeholder="Select a policy"
-              singleSelection={{ asPlainText: true }}
-              options={policies}
-              selectedOptions={selectedPolicy}
-              onChange={(e) => {
-                onSelectedPolicy(e);
-              }}
-            />
-          </EuiFormRow>
-          <EuiFormRow label="Assigned standard fields" fullWidth>
-            <EuiBasicTable
-              items={fields}
-              columns={assignedPolicyColumns}
-              rowProps={getRowProps}
-              cellProps={getCellProps}
-            />
-          </EuiFormRow>
-          <EuiFormRow label="Assigned groups" fullWidth>
-            <EuiBasicTable
-              items={assignedPolicyGroups}
-              columns={assignedPolicyGroupColumns}
-            />
-          </EuiFormRow>
-        </EuiForm>
-      </>
-    );
-  }
-);
+import {
+  findUserBySub,
+  getSources,
+  getPolicies,
+  getStdFields,
+  getGroups,
+  createPolicy,
+  deletePolicy,
+  addSourceToPolicy,
+  addFieldToPolicy,
+  addPolicyToGroup,
+  removeSourceFromPolicy,
+  removeFieldFromPolicy,
+  removePolicyFromGroup,
+  getUser,
+} from '../../services/GatekeeperService';
 
 const Policies = () => {
-  const [globalState, globalActions] = store();
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
   const [isSwitchChecked, setIsSwitchChecked] = useState(false);
   const [policyName, setPolicyName] = useState('');
   const [selectedSource, setSelectedSource] = useState();
+
   const [open, setOpen] = useState(false);
   const [alertMessage, setAlertMessage] = useState('');
   const [severity, setSeverity] = useState('info');
+
   const [optPolicies, setOptPolicies] = useState([]);
   const [selectedPolicy, setSelectedPolicy] = useState();
   const [optStdFields, setOptStdFields] = useState([]);
   const [assignedPolicyItems, setAssignedPolicyItems] = useState([]);
+  const [assignedSources, setAssignedSources] = useState([]);
   const [policies, setPolicies] = useState([]);
   const [optGroupPolicies, setOptGroupPolicies] = useState([]);
   const [optGroups, setOPtGroups] = useState([]);
@@ -316,125 +54,124 @@ const Policies = () => {
   const [optSources, setOptSources] = useState([]);
 
   const loadSources = useCallback(async () => {
-    if (sessionStorage.getItem('userId')) {
-      const user = await globalActions.user.findOneUserWithGroupAndRole(
-        sessionStorage.getItem('userId')
-      );
-      const role = user[0].roleid;
-      let result;
-      if (role === 1) {
-        result = await globalActions.source.allIndexedSources();
-      } else {
-        result = await globalActions.source.indexedSources(
-          sessionStorage.getItem('userId')
-        );
-      }
-      if (result) {
-        const _sources = [];
-        for (const source of result) {
-          _sources.push({ value: source.id, label: source.name });
-        }
-        setOptSources(_sources);
+    const user = await findUserBySub(getUser().profile.sub);
+    const role = user.roles[0].roleid;
+    let result;
+    if (role === 1) {
+      result = await getSources();
+    } else {
+      result = await getSources(); // TODO load sources for user
+    }
+    if (result) {
+      const _sources = [];
+      for (const source of result) {
+        _sources.push({ value: source.id, label: source.name });
       }
+      setOptSources(_sources);
     }
-  }, [globalActions.source, globalActions.user]);
+  }, [findUserBySub]);
 
   const loadPolicies = useCallback(async () => {
-    if (sessionStorage.getItem('userId')) {
-      const user = await globalActions.user.findOneUserWithGroupAndRole(
-        sessionStorage.getItem('userId')
-      );
-      const role = user[0].roleid;
-      let result;
-      if (role === 1) {
-        result = await globalActions.policy.getPolicies();
-      } else {
-        result = await globalActions.policy.getPoliciesByUser(
-          sessionStorage.getItem('userId')
-        );
-      }
-      if (result) {
-        const _policies = [];
-        for (const policy of result) {
-          _policies.push({ value: policy.id, label: policy.name });
-        }
-        setOptPolicies(_policies);
-        setOptGroupPolicies(_policies);
-        setOptSourcePolicies(_policies);
-      }
+    const user = await findUserBySub(getUser().profile.sub);
+    const role = user.roles[0].roleid;
+    let result;
+    if (role === 1) {
+      result = await getPolicies();
+    } else {
+      result = await getPolicies(); // TODO load policies for user
     }
-  }, [globalActions.policy, globalActions.user]);
-
-  const loadPoliciesWithSources = useCallback(async () => {
-    if (sessionStorage.getItem('userId')) {
-      const user = await globalActions.user.findOneUserWithGroupAndRole(
-        sessionStorage.getItem('userId')
-      );
-      const role = user[0].roleid;
-      let result;
-      if (role === 1) {
-        result = await globalActions.policy.getPoliciesWithSources();
-      } else {
-        result = await globalActions.policy.getPoliciesWithSourcesByUser(
-          sessionStorage.getItem('userId')
-        );
-      }
-      if (result) {
-        const policyList = [];
-        const policyNames = [];
-        result.forEach((policy) => {
-          if (policyNames.includes(policy.policyname)) {
-            policyList[policyNames.indexOf(policy.policyname)].sourcename =
-              `${policyList[policyNames.indexOf(policy.policyname)].sourcename}, ${policy.sourcename}`;
-          } else {
-            policyNames.push(policy.policyname);
-            policyList.push(policy);
-          }
-        });
-        setPolicies(policyList);
+    if (result) {
+      const _policies = [];
+      for (const policy of result) {
+        _policies.push({ value: policy.id, label: policy.name });
       }
+      result = result.map((policy) => {
+        return {
+          id: policy.id,
+          policyname: policy.name,
+          sourcename: policy.sources.map((source) => source.source.name).join(', '),
+        };
+      });
+      setPolicies(result);
+      setOptPolicies(_policies);
+      setOptGroupPolicies(_policies);
+      setOptSourcePolicies(_policies);
     }
-  }, [globalActions.policy, globalActions.user]);
+  }, [getPolicies]);
 
   const loadStdFields = useCallback(async () => {
-    const result = await globalActions.source.privateFields();
+    let result = await getStdFields();
     if (result) {
+      result = result.filter((field) => !field.ispublic);
       const _fields = [];
       for (const field of result) {
         _fields.push({ value: field.id, label: field.field_name });
       }
       setOptStdFields(_fields);
     }
-  }, [globalActions.source]);
+  }, [getStdFields]);
 
   const loadGroups = useCallback(async () => {
-    const _groups = await globalActions.group.getGroups();
+    const _groups = await getGroups();
     if (_groups) {
       const groups = [];
       for (const group of _groups) {
-        groups.push({ value: group.id, label: group.name });
+        groups.push({
+          value: group.id,
+          label: group.name,
+          description: group.description,
+        });
       }
       setOPtGroups(groups);
     }
-  }, [globalActions.group]);
+  }, [getGroups]);
 
   useEffect(() => {
-    // clean up controller
-    let isSubscribed = true;
+    loadSources();
+    loadPolicies();
+    loadStdFields();
+    loadGroups();
+    onSelectedPolicy([]);
+    setPolicyName('');
+  }, [loadGroups, loadPolicies, loadSources, loadStdFields, selectedTabNumber]);
 
-    if (isSubscribed) {
-      loadSources();
-      loadPolicies();
-      loadStdFields();
-      loadPoliciesWithSources();
-      loadGroups();
+  const onSwitchChange = () => {
+    setIsSwitchChecked(!isSwitchChecked);
+  };
+
+  const onSaveNewPolicy = async (e) => {
+    e.preventDefault();
+    if (policyName) {
+      const result = await createPolicy(policyName);
+      if (result.id) {
+        setAlertMessage('Policy created.');
+        setSeverity('success');
+        setPolicyName('');
+        loadPolicies();
+      } else {
+        setAlertMessage('Policy not created.');
+        setSeverity('error');
+      }
+      setOpen(true);
     }
+  };
 
-    // cancel subscription to useEffect
-    return () => (isSubscribed = false);
-  }, [loadGroups, loadPolicies, loadPoliciesWithSources, loadSources, loadStdFields]);
+  const onDeletePolicy = async (e) => {
+    if (!e.id) return;
+    const response = await deletePolicy(e.id);
+    if (response && response.success) {
+      setAlertMessage('Policy deleted.');
+      setSeverity('success');
+      loadPolicies();
+    } else {
+      setAlertMessage('Policy not deleted.');
+      setSeverity('error');
+    }
+    setOpen(true);
+  };
 
-  const onPolicySourceAssignment = async () => {
+  const onPolicySourceAssignment = async (e) => {
+    e.preventDefault();
     const checkedPolicies = optSourcePolicies.filter((e) => {
       return e.checked === 'on';
     });
@@ -446,41 +183,17 @@ const Policies = () => {
     if (checkedPolicies && checkedSources) {
       for (const policy of checkedPolicies) {
         for (const source of checkedSources) {
-          await globalActions.policy.createPolicySource(policy.value, source.value);
+          await addSourceToPolicy(source.value, policy.value);
         }
       }
-
-      if (globalState.status === 'SUCCESS') {
-        loadPoliciesWithSources();
-        setOpen(true);
-        setAlertMessage('Policies-Source assignment completed successfully !');
-        setSeverity('success');
-      }
-    }
-  };
-
-  const onSwitchChange = () => {
-    setIsSwitchChecked(!isSwitchChecked);
-  };
-
-  const onSaveNewPolicy = async () => {
-    if (policyName && sessionStorage.getItem('userId')) {
-      await globalActions.policy.createPolicy(
-        policyName,
-        sessionStorage.getItem('userId')
-      );
-
-      if (globalState.status === 'SUCCESS') {
-        setOpen(true);
-        setAlertMessage('Policy created.');
-        setSeverity('success');
-        loadPolicies();
-        loadPoliciesWithSources();
-      }
     }
+    setOptSourcePolicies(optSourcePolicies.map((e) => ({ ...e, checked: null })));
+    setOptSources(optSources.map((e) => ({ ...e, checked: null })));
+    loadPolicies();
   };
 
-  const onPolicyAssignment = async () => {
+  const onPolicyAssignment = async (e) => {
+    e.preventDefault();
     const checkedPolicies = optPolicies.filter((e) => {
       return e.checked === 'on';
     });
@@ -488,22 +201,19 @@ const Policies = () => {
     const checkedStdFields = optStdFields.filter((e) => {
       return e.checked === 'on';
     });
-
     for (const policy of checkedPolicies) {
       for (const stdField of checkedStdFields) {
-        //to-do: if policies is already defined, do not let insert them into table.
-        await globalActions.policy.createPolicyField(policy.value, stdField.value);
+        await addFieldToPolicy(stdField.value, policy.value);
       }
     }
 
-    if (globalState.status === 'SUCCESS') {
-      setOpen(true);
-      setAlertMessage('Policies-Assignment completed.');
-      setSeverity('success');
-    }
+    setOptPolicies(optPolicies.map((e) => ({ ...e, checked: null })));
+    setOptStdFields(optStdFields.map((e) => ({ ...e, checked: null })));
+    loadPolicies();
   };
 
-  const onPolicyGroupAssignment = async () => {
+  const onPolicyGroupAssignment = async (e) => {
+    e.preventDefault();
     const checkedPolicies = optGroupPolicies.filter((e) => {
       return e.checked === 'on';
     });
@@ -515,184 +225,110 @@ const Policies = () => {
     if (checkedPolicies && checkedGroups) {
       for (const group of checkedGroups) {
         for (const policy of checkedPolicies) {
-          await globalActions.group.createGroupPolicy(group.value, policy.value);
+          await addPolicyToGroup(policy.value, group.value);
         }
       }
-      if (globalState.status === 'SUCCESS') {
-        setOpen(true);
-        setAlertMessage('Policies-Group assignment completed.');
-        setSeverity('success');
-      }
+
+      setOptGroupPolicies(optGroupPolicies.map((e) => ({ ...e, checked: null })));
+      setOPtGroups(optGroups.map((e) => ({ ...e, checked: null })));
+      loadPolicies();
     }
   };
 
   const onSelectedPolicy = async (e) => {
     if (e.length > 0) {
-      const aPolicies = await globalActions.policy.getAssignedPolicies(e[0].value);
-      const groupDetailsByPolicy = await globalActions.policy.getGroupDetailsByPolicy(
-        e[0].value
-      );
-
-      if (aPolicies) {
-        const policyItemsList = [];
-        const fieldNames = [];
-        aPolicies.forEach((aPolicy) => {
-          if (!fieldNames.includes(aPolicy.field_name)) {
-            fieldNames.push(aPolicy.field_name);
-            policyItemsList.push(aPolicy);
-          }
-        });
-        setAssignedPolicyItems(policyItemsList);
+      const policies = await getPolicies();
+      const selected = policies.find((policy) => {
+        return policy.id === e[0].value;
+      });
+
+      const policyItems = selected.std_fields.map((field) => {
+        return {
+          id: field.std_field.id,
+          field_name: field.std_field.field_name,
+          definition_and_comment: field.std_field.definition_and_comment,
+          field_type: field.std_field.field_type,
+        };
+      });
+      setAssignedPolicyItems(policyItems);
+
+      let assignedSources = [];
+      for (const source of selected.sources) {
+        let assignedSource = {};
+        assignedSource.id = source.source.id;
+        assignedSource.source_name = source.source.name;
+        assignedSource.source_description = source.source.description;
+        assignedSources.push(assignedSource);
       }
-
-      if (groupDetailsByPolicy) {
-        const policyGroupList = [];
-        const groupIds = [];
-        groupDetailsByPolicy.forEach((groupDetail) => {
-          if (groupIds.includes(groupDetail.groupid)) {
-            policyGroupList[groupIds.indexOf(groupDetail.groupid)].source_name =
-              `${policyGroupList[groupIds.indexOf(groupDetail.groupid)].source_name}, ${groupDetail.source_name}`;
-          } else {
-            groupIds.push(groupDetail.groupid);
-            policyGroupList.push(groupDetail);
-          }
-        });
-        setAssignedPolicyGroups(policyGroupList);
+      setAssignedSources(assignedSources);
+
+      let assignedGroups = [];
+      for (const group of selected.groups) {
+        //console.log(group);
+        let assignedGroup = {};
+        assignedGroup.id = group.group.id;
+        assignedGroup.group_name = group.group.name;
+        assignedGroup.group_description = group.group.description;
+        assignedGroups.push(assignedGroup);
       }
-
+      setAssignedPolicyGroups(assignedGroups);
       setSelectedPolicy(e);
     } else {
-      setSelectedPolicy(e);
+      setSelectedPolicy([]);
+      setAssignedPolicyItems([]);
+      setAssignedSources([]);
+      setAssignedPolicyGroups([]);
     }
   };
 
-  const onDeletePolicyField = async (e) => {
-    if (e.id) {
-      await globalActions.policy.deletePolicyField(e.id);
-
+  const onDeletePolicySource = async (e) => {
+    if (e.id && selectedPolicy.length > 0) {
+      const result = await removeSourceFromPolicy(e.id, selectedPolicy[0].value);
+      if (result && result.success) {
+        setAlertMessage('Policies-Source deleted.');
+        setSeverity('success');
+        onSelectedPolicy(selectedPolicy);
+        loadPolicies();
+      } else {
+        setAlertMessage('Policies-Source not deleted.');
+        setSeverity('error');
+      }
       setOpen(true);
-      setAlertMessage('Policies-Field deleted.');
-      setSeverity('success');
     }
   };
 
-  const assignedPolicyActions = [
-    {
-      name: 'Delete',
-      description: 'Delete this policies-field',
-      icon: 'trash',
-      type: 'icon',
-      color: 'danger',
-      onClick: onDeletePolicyField,
-    },
-  ];
-
-  const assignedPolicyColumns = [
-    {
-      field: 'field_name',
-      name: 'Field name',
-      sortable: true,
-    },
-    {
-      field: 'definition_and_comment',
-      name: 'Definition and comment',
-      truncateText: true,
-      mobileOptions: {
-        show: false,
-      },
-    },
-    {
-      field: 'field_type',
-      name: 'Field type',
-    },
-    {
-      name: 'Actions',
-      actions: assignedPolicyActions,
-    },
-  ];
-
-  const onAssignedPolicyGroup = async (e) => {
-    if (e.grouppolicyid) {
-      await globalActions.group.deleteGroupPolicy(e.grouppolicyid);
-
+  const onDeletePolicyField = async (e) => {
+    if (e.id && selectedPolicy.length > 0) {
+      const result = await removeFieldFromPolicy(e.id, selectedPolicy[0].value);
+      if (result && result.success) {
+        setAlertMessage('Policies-Field deleted.');
+        setSeverity('success');
+        onSelectedPolicy(selectedPolicy);
+        loadPolicies();
+      } else {
+        setAlertMessage('Policies-Field not deleted.');
+        setSeverity('error');
+      }
       setOpen(true);
-      setAlertMessage('Policies-groups deleted.');
-      setSeverity('success');
     }
   };
 
-  const assignedPolicyGroupActions = [
-    {
-      name: 'Delete',
-      description: 'Delete this policies-group',
-      icon: 'trash',
-      type: 'icon',
-      color: 'danger',
-      onClick: onAssignedPolicyGroup,
-    },
-  ];
-
-  const assignedPolicyGroupColumns = [
-    { field: 'group_name', name: 'Group name' },
-    { field: 'source_name', name: 'Source name' },
-    { field: 'source_description', name: 'Source description' },
-    { name: 'Actions', actions: assignedPolicyGroupActions },
-  ];
-
-  const onDeletePolicy = async (e) => {
-    await globalActions.policy.deletePolicy(e.id);
-    if (globalState.status === 'SUCCESS') {
+  const onDeletePolicyGroup = async (e) => {
+    if (e.id && selectedPolicy.length > 0) {
+      const result = await removePolicyFromGroup(selectedPolicy[0].value, e.id);
+      if (result && result.success) {
+        setAlertMessage('Policies-Group deleted.');
+        setSeverity('success');
+        onSelectedPolicy(selectedPolicy);
+        loadPolicies();
+      } else {
+        setAlertMessage('Policies-Group not deleted.');
+        setSeverity('error');
+      }
       setOpen(true);
-      setAlertMessage('Policy deleted.');
-      setSeverity('success');
-      loadPoliciesWithSources();
-      loadPolicies();
     }
   };
 
-  const policyColumnAction = [
-    {
-      name: 'Delete',
-      description: 'Delete this policy',
-      icon: 'trash',
-      type: 'icon',
-      color: 'danger',
-      onClick: onDeletePolicy,
-    },
-  ];
-  const policyColumns = [
-    {
-      field: 'policyname',
-      name: 'Policy name',
-    },
-    {
-      field: 'sourcename',
-      name: 'Source name',
-    },
-    {
-      name: 'Actions',
-      actions: policyColumnAction,
-    },
-  ];
-
-  const getRowProps = (item) => {
-    const { id } = item;
-    return {
-      'data-test-subj': `row-${id}`,
-      className: 'customRowClass',
-    };
-  };
-
-  const getCellProps = (item, column) => {
-    const { id } = item;
-    const { field } = column;
-    return {
-      className: 'customCellClass',
-      'data-test-subj': `cell-${id}-${field}`,
-      textOnly: true,
-    };
-  };
-
   const handleClose = (event, reason) => {
     if (reason === 'clickaway') {
       return;
@@ -708,7 +344,6 @@ const Policies = () => {
         <>
           <br />
           <NewPolicyForm
-            globalState={globalState}
             policyName={policyName}
             setPolicyName={setPolicyName}
             isSwitchChecked={isSwitchChecked}
@@ -717,8 +352,8 @@ const Policies = () => {
             selectedSource={selectedSource}
             setSelectedSource={setSelectedSource}
             onSaveNewPolicy={onSaveNewPolicy}
+            onDeletePolicy={onDeletePolicy}
             policies={policies}
-            policyColumns={policyColumns}
           />
         </>
       ),
@@ -730,7 +365,6 @@ const Policies = () => {
         <>
           <br />
           <PolicySourceAssignment
-            globalState={globalState}
             optPolicies={optSourcePolicies}
             setOptPolicies={setOptSourcePolicies}
             optSources={optSources}
@@ -747,7 +381,6 @@ const Policies = () => {
         <>
           <br />
           <PolicyAssignment
-            globalState={globalState}
             optPolicies={optPolicies}
             setOptPolicies={setOptPolicies}
             optStdFields={optStdFields}
@@ -764,7 +397,6 @@ const Policies = () => {
         <>
           <br />
           <PolicyGroupAssignment
-            globalState={globalState}
             optPolicies={optGroupPolicies}
             setOptPolicies={setOptGroupPolicies}
             optGroups={optGroups}
@@ -783,13 +415,13 @@ const Policies = () => {
           <AssignedPolicies
             policies={optPolicies}
             selectedPolicy={selectedPolicy}
-            fields={assignedPolicyItems}
-            assignedPolicyColumns={assignedPolicyColumns}
-            getRowProps={getRowProps}
-            getCellProps={getCellProps}
             onSelectedPolicy={onSelectedPolicy}
+            assignedPolicySources={assignedSources}
+            assignedPolicyFields={assignedPolicyItems}
             assignedPolicyGroups={assignedPolicyGroups}
-            assignedPolicyGroupColumns={assignedPolicyGroupColumns}
+            onDeletePolicySource={onDeletePolicySource}
+            onDeletePolicyField={onDeletePolicyField}
+            onDeletePolicyGroup={onDeletePolicyGroup}
           />
         </>
       ),
diff --git a/src/pages/policies/PolicyAssignment.js b/src/pages/policies/PolicyAssignment.js
new file mode 100644
index 0000000..44cfbc0
--- /dev/null
+++ b/src/pages/policies/PolicyAssignment.js
@@ -0,0 +1,68 @@
+import {
+  EuiButton,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiForm,
+  EuiFormRow,
+  EuiSelectable,
+  EuiSpacer,
+} from '@elastic/eui';
+import React, { Fragment, memo } from 'react';
+
+const PolicyAssignment = memo(
+  ({
+    optPolicies,
+    setOptPolicies,
+    optStdFields,
+    setOptStdFields,
+    onPolicyAssignment,
+  }) => {
+    return (
+      <>
+        <EuiForm component="form">
+          <EuiFlexGroup component="span">
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Policies" fullWidth>
+                <EuiSelectable
+                  searchable
+                  singleSelection={true}
+                  options={optPolicies}
+                  onChange={(newOptions) => setOptPolicies(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Standard fields" fullWidth>
+                <EuiSelectable
+                  searchable
+                  options={optStdFields}
+                  onChange={(newOptions) => setOptStdFields(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+          </EuiFlexGroup>
+          <EuiSpacer />
+          <EuiButton type="submit" onClick={onPolicyAssignment} fill>
+            Save
+          </EuiButton>
+        </EuiForm>
+      </>
+    );
+  }
+);
+
+export default PolicyAssignment;
diff --git a/src/pages/policies/PolicyGroupAssignment.js b/src/pages/policies/PolicyGroupAssignment.js
new file mode 100644
index 0000000..7233a2b
--- /dev/null
+++ b/src/pages/policies/PolicyGroupAssignment.js
@@ -0,0 +1,62 @@
+import {
+  EuiButton,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiForm,
+  EuiFormRow,
+  EuiSelectable,
+  EuiSpacer,
+} from '@elastic/eui';
+import React, { Fragment, memo } from 'react';
+
+const PolicyGroupAssignment = memo(
+  ({ optPolicies, setOptPolicies, optGroups, setOPtGroups, onPolicyGroupAssignment }) => {
+    return (
+      <>
+        <EuiForm component="form">
+          <EuiFlexGroup component="span">
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Policies" fullWidth>
+                <EuiSelectable
+                  searchable
+                  singleSelection={true}
+                  options={optPolicies}
+                  onChange={(newOptions) => setOptPolicies(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Groups" fullWidth>
+                <EuiSelectable
+                  searchable
+                  options={optGroups}
+                  onChange={(newOptions) => setOPtGroups(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+          </EuiFlexGroup>
+          <EuiSpacer />
+          <EuiButton type="submit" onClick={onPolicyGroupAssignment} fill>
+            Save
+          </EuiButton>
+        </EuiForm>
+      </>
+    );
+  }
+);
+
+export default PolicyGroupAssignment;
diff --git a/src/pages/policies/PolicySourceAssignment.js b/src/pages/policies/PolicySourceAssignment.js
new file mode 100644
index 0000000..4db353b
--- /dev/null
+++ b/src/pages/policies/PolicySourceAssignment.js
@@ -0,0 +1,69 @@
+import {
+  EuiButton,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiForm,
+  EuiFormRow,
+  EuiSelectable,
+  EuiSpacer,
+} from '@elastic/eui';
+import React, { Fragment, memo } from 'react';
+
+const PolicySourceAssignment = memo(
+  ({
+    optPolicies,
+    setOptPolicies,
+    optSources,
+    setOptSources,
+    onPolicySourceAssignment,
+  }) => {
+    return (
+      <>
+        <EuiForm component="form">
+          <EuiFlexGroup component="span">
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Policies" fullWidth>
+                <EuiSelectable
+                  searchable
+                  singleSelection={true}
+                  options={optPolicies}
+                  onChange={(newOptions) => setOptPolicies(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Sources" fullWidth>
+                <EuiSelectable
+                  searchable
+                  singleSelection={false}
+                  options={optSources}
+                  onChange={(newOptions) => setOptSources(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+          </EuiFlexGroup>
+          <EuiSpacer />
+          <EuiButton type="submit" onClick={onPolicySourceAssignment} fill>
+            Save
+          </EuiButton>
+        </EuiForm>
+      </>
+    );
+  }
+);
+
+export default PolicySourceAssignment;
diff --git a/src/pages/requests/Requests.js b/src/pages/requests/Requests.js
index 04d3fcd..5d2387b 100644
--- a/src/pages/requests/Requests.js
+++ b/src/pages/requests/Requests.js
@@ -1,5 +1,4 @@
 import React, { useState, useCallback, useEffect, memo } from 'react';
-import store from '../../store/index';
 import { ShowAlert } from '../../components/Common/Common';
 import {
   EuiForm,
@@ -12,6 +11,12 @@ import {
   EuiFormRow,
   EuiBasicTable,
 } from '@elastic/eui';
+import {
+  getRequests,
+  getPendingRequests,
+  deleteUserRequest,
+  updateUserRequest,
+} from '../../services/GatekeeperService';
 
 const RequestList = memo(({ requests, requestColumns }) => {
   return (
@@ -31,7 +36,6 @@ const RequestList = memo(({ requests, requestColumns }) => {
 });
 
 const Requests = () => {
-  const [, globalActions] = store();
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
   const [open, setOpen] = useState(false);
   const [alertMessage, setAlertMessage] = useState('');
@@ -40,64 +44,54 @@ const Requests = () => {
   const [pendingRequests, setPendingRequests] = useState([]);
 
   const loadRequests = useCallback(async () => {
-    const requestList = await globalActions.user.fetchRequests();
+    const requestList = await getRequests();
     if (requestList) {
       setRequests(requestList);
     }
-  }, [globalActions.user]);
+  }, [getRequests]);
 
   const loadPendingRequests = useCallback(async () => {
-    const requestList = await globalActions.user.fetchPendingRequests();
+    const requestList = await getPendingRequests();
     if (requestList) {
       setPendingRequests(requestList);
     }
-  }, [globalActions.user]);
+  }, [getPendingRequests]);
 
   useEffect(() => {
-    // clean up controller
-    let isSubscribed = true;
-    if (isSubscribed) {
-      loadRequests();
-      loadPendingRequests();
-    }
-    // cancel subscription to useEffect
-    return () => (isSubscribed = false);
+    loadRequests();
+    loadPendingRequests();
   }, [loadRequests, loadPendingRequests]);
 
   const onDeleteRequest = async (request) => {
-    if (!request) {
-      return;
-    }
-    const result = await globalActions.user.deleteUserRequest(request.id);
-    if (result && !result.error) {
-      setAlertMessage('Request has been deleted.');
-      setSeverity('success');
-      setOpen(true);
-    } else {
-      setAlertMessage(`Error: ${result.error}`);
-      setSeverity('error');
+    if (request) {
+      const result = await deleteUserRequest(request.id);
+      if (result) {
+        setAlertMessage('Request has been deleted.');
+        setSeverity('success');
+        await loadRequests();
+        await loadPendingRequests();
+      } else {
+        setAlertMessage(`Error: ${result.error}`);
+        setSeverity('error');
+      }
       setOpen(true);
     }
-    await loadRequests();
-    await loadPendingRequests();
   };
 
   const onProcessRequest = async (request) => {
-    if (!request) {
-      return;
-    }
-    const result = await globalActions.user.processUserRequest(request.id);
-    if (result && !result.error) {
-      setAlertMessage('Request has been processed.');
-      setSeverity('success');
-      setOpen(true);
-    } else {
-      setAlertMessage(`Error: ${result.error}`);
-      setSeverity('error');
+    if (request) {
+      const result = await updateUserRequest(request.id, true);
+      if (result) {
+        setAlertMessage('Request has been processed.');
+        setSeverity('success');
+        await loadRequests();
+        await loadPendingRequests();
+      } else {
+        setAlertMessage(`Error: ${result.error}`);
+        setSeverity('error');
+      }
       setOpen(true);
     }
-    await loadRequests();
-    await loadPendingRequests();
   };
 
   const requestActions = [
diff --git a/src/pages/roles/Roles.js b/src/pages/roles/Roles.js
index 4706c0f..4f59de7 100644
--- a/src/pages/roles/Roles.js
+++ b/src/pages/roles/Roles.js
@@ -1,5 +1,4 @@
 import React, { useState, Fragment, useCallback, useEffect } from 'react';
-import store from '../../store/index';
 import { ShowAlert } from '../../components/Common';
 import {
   EuiForm,
@@ -19,104 +18,107 @@ import {
   EuiSelectable,
   EuiComboBox,
 } from '@elastic/eui';
+import {
+  getRoles,
+  getUsers,
+  createRole,
+  addUserToRole,
+  deleteRole,
+} from '../../services/GatekeeperService';
 
 const newRoleForm = ({
   roleNameValue,
   setRoleNameValue,
   roleDescriptionValue,
   setRoleDescriptionValue,
-  globalState,
+  roles,
   onSaveRole,
   roleColumns,
 }) => {
   return (
-    <>
-      <EuiForm component="form">
-        <EuiFormRow label="Name">
-          <EuiFieldText
-            value={roleNameValue}
-            onChange={(e) => setRoleNameValue(e.target.value)}
-          />
-        </EuiFormRow>
-        <EuiFormRow label="Description">
-          <EuiFieldText
-            value={roleDescriptionValue}
-            onChange={(e) => setRoleDescriptionValue(e.target.value)}
-          />
-        </EuiFormRow>
-        <EuiSpacer />
-        {
-          <EuiButton fill onClick={onSaveRole} isLoading={globalState.isLoading}>
-            Save
-          </EuiButton>
-        }
-        <EuiSpacer />
-        <EuiFormRow label="" fullWidth>
-          <EuiBasicTable
-            items={globalState.roles}
-            rowheader="Name"
-            columns={roleColumns}
-            // rowProps={getRowProps}
-            // cellProps={getCellProps}
-          />
-        </EuiFormRow>
-      </EuiForm>
-    </>
+    roles &&
+    roles.length > 0 && (
+      <>
+        <EuiForm component="form">
+          <EuiFormRow label="Name">
+            <EuiFieldText
+              value={roleNameValue || ''}
+              onChange={(e) => setRoleNameValue(e.target.value)}
+            />
+          </EuiFormRow>
+          <EuiFormRow label="Description">
+            <EuiFieldText
+              value={roleDescriptionValue || ''}
+              onChange={(e) => setRoleDescriptionValue(e.target.value)}
+            />
+          </EuiFormRow>
+          <EuiSpacer />
+          {
+            <EuiButton fill onClick={onSaveRole}>
+              Save
+            </EuiButton>
+          }
+          <EuiSpacer />
+          <EuiFormRow label="" fullWidth>
+            <EuiBasicTable items={roles} rowheader="Name" columns={roleColumns} />
+          </EuiFormRow>
+        </EuiForm>
+      </>
+    )
   );
 };
-const roleAssignment = (
-  globalState,
-  roles,
-  setRoles,
-  users,
-  setUsers,
-  onRoleAssignment
-) => {
+
+const roleAssignment = (roles, setRoles, users, setUsers, onRoleAssignment) => {
   return (
-    <>
-      <EuiForm component="form">
-        <EuiFlexGroup component="span">
-          <EuiFlexItem component="span">
-            <EuiFormRow label="Roles" fullWidth>
-              <EuiSelectable
-                searchable
-                singleSelection={true}
-                options={roles}
-                onChange={(newOptions) => setRoles(newOptions)}
-              >
-                {(list, search) => (
-                  <Fragment>
-                    {search}
-                    {list}
-                  </Fragment>
-                )}
-              </EuiSelectable>
-            </EuiFormRow>
-          </EuiFlexItem>
-          <EuiFlexItem component="span">
-            <EuiFormRow label="Users" fullWidth>
-              <EuiSelectable
-                searchable
-                options={users}
-                onChange={(newOptions) => setUsers(newOptions)}
-              >
-                {(list, search) => (
-                  <Fragment>
-                    {search}
-                    {list}
-                  </Fragment>
-                )}
-              </EuiSelectable>
-            </EuiFormRow>
-          </EuiFlexItem>
-        </EuiFlexGroup>
-        <EuiSpacer />
+    roles &&
+    users &&
+    roles.length > 0 &&
+    users.length > 0 && (
+      <>
+        <EuiForm component="form">
+          <EuiFlexGroup component="span">
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Roles" fullWidth>
+                <EuiSelectable
+                  searchable
+                  singleSelection={true}
+                  options={roles}
+                  onChange={(newOptions) => setRoles(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+            <EuiFlexItem component="span">
+              <EuiFormRow label="Users" fullWidth>
+                <EuiSelectable
+                  searchable
+                  options={users}
+                  onChange={(newOptions) => setUsers(newOptions)}
+                >
+                  {(list, search) => (
+                    <Fragment>
+                      {search}
+                      {list}
+                    </Fragment>
+                  )}
+                </EuiSelectable>
+              </EuiFormRow>
+            </EuiFlexItem>
+          </EuiFlexGroup>
+          <EuiSpacer />
 
-        <EuiButton type="submit" onClick={onRoleAssignment} fill>
-          Save
-        </EuiButton>
-      </EuiForm>
-    </>
+          <EuiButton type="submit" onClick={onRoleAssignment} fill>
+            Save
+          </EuiButton>
+        </EuiForm>
+      </>
+    )
   );
 };
 const assignedRoles = ({
@@ -132,7 +134,7 @@ const assignedRoles = ({
         <EuiFormRow label="Select specific roles">
           <EuiComboBox
             placeholder="Select a role"
-            singleSelection={{ asPlainText: true }}
+            singleSelection={true}
             options={roles}
             selectedOptions={selectedRole}
             onChange={(e) => {
@@ -145,8 +147,6 @@ const assignedRoles = ({
             items={assignedRoleToUsers}
             rowheader=""
             columns={assignedRolesColumns}
-            // rowProps={getRowProps}
-            // cellProps={getCellProps}
           />
         </EuiFormRow>
       </EuiForm>
@@ -155,56 +155,71 @@ const assignedRoles = ({
 };
 
 const Roles = () => {
-  const [globalState, globalActions] = store();
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
   const [roleNameValue, setRoleNameValue] = useState();
   const [roleDescriptionValue, setRoleDescriptionValue] = useState();
   const [roles, setRoles] = useState([]);
   const [users, setUsers] = useState([]);
-  const [open, setOpen] = useState(false);
+
   const [alertMessage, setAlertMessage] = useState('');
   const [severity, setSeverity] = useState('info');
+  const [open, setOpen] = useState(false);
+
   const [selectedRole, setSelectedRole] = useState();
   const [assignedRoleToUsers, setAssignedRoleToUsers] = useState([]);
 
   const loads = useCallback(async () => {
-    const roles = await globalActions.user.findRole();
-    const users = await globalActions.user.findUser();
-    if (globalState.user.id) {
-      await globalActions.user.allocatedRoles(globalState.user.id);
-    }
+    const roles = await getRoles();
+    const users = await getUsers();
 
     if (roles && users) {
       const _roles = [];
       for (const role of roles) {
-        _roles.push({ value: role.id, label: role.name });
+        _roles.push({
+          value: role.id,
+          label: role.name,
+          description: role.description,
+          users: role.users,
+        });
       }
       setRoles(_roles);
 
       const _users = [];
       for (const user of users) {
-        _users.push({ value: user.id, label: user.username });
+        _users.push({ value: user.id, label: user.email, sub: user.kc_id });
       }
       setUsers(_users);
     }
-  }, [globalActions.user, globalState.user.id]);
+  }, []);
 
   useEffect(() => {
-    // clean up controller
-    let isSubscribed = true;
-    if (isSubscribed) {
-      loads();
-    }
-    // cancel subscription to useEffect
-    return () => (isSubscribed = false);
+    setSelectedRole([]);
+    setAssignedRoleToUsers([]);
+    loads();
+  }, [loads, selectedTabNumber]);
+
+  useEffect(() => {
+    loads();
   }, [loads]);
 
-  const onSaveRole = async () => {
-    await globalActions.user.createRole(roleNameValue, roleDescriptionValue);
-    await globalActions.user.findRole();
+  const onSaveRole = async (e) => {
+    e.preventDefault();
+    const result = await createRole(roleNameValue, roleDescriptionValue);
+    if (result) {
+      setAlertMessage('Role has been created.');
+      setSeverity('success');
+    } else {
+      setAlertMessage('Role has not been created.');
+      setSeverity('error');
+    }
+    setOpen(true);
+    setRoleNameValue('');
+    setRoleDescriptionValue('');
+    await loads();
   };
 
-  const onRoleAssignment = async () => {
+  const onRoleAssignment = async (e) => {
+    e.preventDefault();
     const checkedRoles = roles.filter((e) => {
       return e.checked === 'on';
     });
@@ -215,37 +230,61 @@ const Roles = () => {
 
     for (const user of checkedUsers) {
       for (const role of checkedRoles) {
-        await globalActions.user.allocateRolesToUser(user.value, role.value);
+        await addUserToRole(user.sub, role.value);
       }
     }
+    await loads();
+    setRoles(roles.map((role) => ({ ...role, checked: null })));
+    setUsers(users.map((user) => ({ ...user, checked: null })));
+  };
 
-    if (globalState.status === 'SUCCESS') {
-      setOpen(true);
-      setAlertMessage('Role assignment was completed.');
+  const removeUserFromRole = async (e) => {
+    const result = await removeUserFromRole(e.sub, e.roleId);
+    if (result) {
+      setAlertMessage('User has been removed from role.');
       setSeverity('success');
+    } else {
+      setAlertMessage('User has not been removed from role.');
+      setSeverity('error');
     }
+    setOpen(true);
+    onSelectedRole([]);
+    await loads();
   };
 
   const onSelectedRole = async (e) => {
     if (e.length > 0) {
       setSelectedRole(e);
-      const assignedUserByRoleItems = await globalActions.user.getAssignedUserByRole(
-        e[0].value
-      );
+      const assignedUserByRoleItems = roles
+        .find((role) => {
+          return role.value === e[0].value;
+        })
+        .users.map((user) => {
+          return {
+            email: user.user.email,
+            rolename: e[0].label,
+            roleId: e[0].value,
+            sub: user.user.kc_id,
+          };
+        });
       setAssignedRoleToUsers(assignedUserByRoleItems);
     } else {
-      setSelectedRole(e);
+      setSelectedRole([]);
+      setAssignedRoleToUsers([]);
     }
   };
 
   const onDeleteRole = async (e) => {
-    await globalActions.user.deleteRole(e.id);
-    if (globalState.status === 'SUCCESS') {
-      setOpen(true);
+    const result = await deleteRole(e.value);
+    if (result) {
       setAlertMessage('Role has been deleted.');
       setSeverity('success');
-      await globalActions.user.findRole();
+    } else {
+      setAlertMessage('Role has not been deleted.');
+      setSeverity('error');
     }
+    setOpen(true);
+    await loads();
   };
 
   const roleActions = [
@@ -258,17 +297,28 @@ const Roles = () => {
       onClick: onDeleteRole,
     },
   ];
+
+  const assignedRoleActions = [
+    {
+      name: 'Remove',
+      description: 'Remove this user from this role',
+      icon: 'trash',
+      type: 'icon',
+      color: 'danger',
+      onClick: removeUserFromRole,
+    },
+  ];
+
   const roleColumns = [
-    { field: 'name', name: 'Name' },
+    { field: 'label', name: 'Name' },
     { field: 'description', name: 'Description' },
     { name: 'Actions', actions: roleActions },
   ];
 
   const assignedRolesColumns = [
-    { field: 'username', name: 'Username' },
-    { field: 'useremail', name: 'E-mail' },
+    { field: 'email', name: 'E-mail' },
     { field: 'rolename', name: 'Role' },
-    { name: 'Actions', actions: roleActions },
+    { name: 'Actions', actions: assignedRoleActions },
   ];
 
   const handleClose = (event, reason) => {
@@ -290,7 +340,7 @@ const Roles = () => {
             setRoleNameValue,
             roleDescriptionValue,
             setRoleDescriptionValue,
-            globalState,
+            roles,
             onSaveRole,
             roleColumns,
           })}
@@ -303,14 +353,7 @@ const Roles = () => {
       content: (
         <>
           <br />
-          {roleAssignment(
-            globalState,
-            roles,
-            setRoles,
-            users,
-            setUsers,
-            onRoleAssignment
-          )}
+          {roleAssignment(roles, setRoles, users, setUsers, onRoleAssignment)}
         </>
       ),
     },
diff --git a/src/pages/sources/Sources.js b/src/pages/sources/Sources.js
index 9718765..11a8d3d 100644
--- a/src/pages/sources/Sources.js
+++ b/src/pages/sources/Sources.js
@@ -1,5 +1,4 @@
 import React, { useState, useCallback, useEffect, memo, useRef } from 'react';
-import store from '../../store/index';
 import {
   EuiForm,
   EuiPageContent,
@@ -18,7 +17,6 @@ import {
   EuiFilePicker,
   EuiBasicTable,
   EuiHealth,
-  EuiProgress,
   EuiConfirmModal,
   EuiOverlayMask,
   EuiModal,
@@ -31,11 +29,17 @@ import {
 } from '@elastic/eui';
 
 import { ShowAlert } from '../../components/Common';
-import JsonView from '@in-sylva/json-view';
+import ReactJson from '@microlink/react-json-view';
+import {
+  getUser,
+  deleteSource,
+  createSource,
+  findUserBySub,
+  getSources,
+} from '../../services/GatekeeperService';
 
 const NewSourceForm = memo(
   ({
-    globalState,
     nameValue,
     setNameValue,
     descriptionValue,
@@ -55,14 +59,14 @@ const NewSourceForm = memo(
               <EuiFormRow label="Source or file name">
                 <EuiFieldText
                   id="nameValue"
-                  value={nameValue}
+                  value={nameValue || ''}
                   onChange={(e) => setNameValue(e.target.value)}
                 />
               </EuiFormRow>
               <EuiFormRow label="Source description">
                 <EuiFieldText
                   id="descriptionValue"
-                  value={descriptionValue}
+                  value={descriptionValue || ''}
                   onChange={(e) => setDescriptionValue(e.target.value)}
                 />
               </EuiFormRow>
@@ -89,7 +93,7 @@ const NewSourceForm = memo(
                   <EuiButton
                     fill
                     onClick={onSaveSource}
-                    isLoading={globalState.isLoading}
+                    disabled={!nameValue || !descriptionValue || !metaUrfms}
                   >
                     Save
                   </EuiButton>
@@ -99,7 +103,7 @@ const NewSourceForm = memo(
             <EuiFlexItem grow={3}>
               <>
                 <br />
-                <JsonView
+                <ReactJson
                   name="Metadata records"
                   collapsed={true}
                   iconStyle={'triangle'}
@@ -152,22 +156,6 @@ const SourcesForm = memo(
   }
 );
 
-const ShareSources = memo(() => {
-  return (
-    <>
-      <br />
-    </>
-  );
-});
-
-const SharedSources = memo(() => {
-  return (
-    <>
-      <br />
-    </>
-  );
-});
-
 const renderFiles = (files) => {
   if (files.length > 0) {
     return (
@@ -185,9 +173,7 @@ const renderFiles = (files) => {
 };
 const Sources = () => {
   const [metaUrfms, setMetaUrfms] = useState([]);
-  // const [metaUrfmsCol, setMetaUrfmsCol] = useState([])
   const [selectedTabNumber, setSelectedTabNumber] = useState(0);
-  const [globalState, globalActions] = store();
   const [files, setFiles] = useState([]);
   const [nameValue, setNameValue] = useState();
   const [descriptionValue, setDescriptionValue] = useState();
@@ -246,19 +232,11 @@ const Sources = () => {
     pageSizeOptions: [3, 5, 8],
   };
 
-  // const unsentSources = (typeof sources === ([] || null) ? [] : sources.filter(e => { return e.is_send === false }))
-
   const selection = {
     selectable: (source) => !source.is_send,
     onSelectionChange: onSelectionChange,
-    // initialSelected: unsentSources,
   };
 
-  /*
-    const onSelection = () => {
-        tableref.current.setSelection(typeof sources === ([] || null) ? [] : sources.filter(e => { return e.is_send === false }));
-    }; */
-
   const sorting = {
     sort: {
       field: sortField,
@@ -280,14 +258,11 @@ const Sources = () => {
 
   const onDeleteSourceConfirm = async () => {
     closeModal();
-    if (source.id && sessionStorage.getItem('userId')) {
-      await globalActions.source.deleteSource(
-        source.id,
-        sessionStorage.getItem('userId')
-      );
-      setOpen(true);
+    if (source.id) {
+      const response = await deleteSource(source.id);
       setAlertMessage('Source is deleted successfully');
       setSeverity('success');
+      setOpen(true);
 
       await loadSources();
     } else {
@@ -301,51 +276,48 @@ const Sources = () => {
 
   const onMergeAndSendSourcesConfirmed = async () => {
     if (sourceName && sourceDescription && selectedSources) {
-      const kcId = sessionStorage.getItem('userId');
-      const result = await globalActions.source.mergeAndSendSource(
-        kcId,
-        sourceName,
-        sourceDescription,
-        selectedSources
-      );
-      if (result.status === 201) {
-        setOpen(true);
-        setAlertMessage('Sources are merged and send to elasticsearch successfully !');
-        setSeverity('success');
-
-        await loadSources();
-      } else {
-        setOpen(true);
-        setAlertMessage('While merging the sources, unexpected error has been occurred.');
-        setSeverity('error');
-      }
-      closeMergeSourceModal();
+      //const kcId = sessionStorage.getItem('userId');
+      // const result = await globalActions.source.mergeAndSendSource(
+      //   kcId,
+      //   sourceName,
+      //   sourceDescription,
+      //   selectedSources
+      // );
+      // if (result.status === 201) {
+      //   setOpen(true);
+      //   setAlertMessage('Sources are merged and send to elasticsearch successfully !');
+      //   setSeverity('success');
+      //   await loadSources();
+      // } else {
+      //   setOpen(true);
+      //   setAlertMessage('While merging the sources, unexpected error has been occurred.');
+      //   setSeverity('error');
+      // }
+      // closeMergeSourceModal();
     }
   };
 
-  const updateSource = async (kc_id, source_id) => {
-    await globalActions.source.updateSource(kc_id, source_id);
-  };
+  // const updateSource = async (kc_id, source_id) => {
+  //   await globalActions.source.updateSource(kc_id, source_id);
+  // };
   // import source document to elasticsearch
   const onSendSource = async (source) => {
     if (sessionStorage.getItem('userId') && source) {
-      const kc_id = sessionStorage.getItem('userId');
-      const source_id = source.id;
-
-      await updateSource(kc_id, source_id);
-      if (globalState.status === 'SUCCESS') {
-        setOpen(true);
-        setAlertMessage('Source imported to elastic stack successfully');
-        setSeverity('success');
-
-        await loadSources();
-      } else {
-        setOpen(true);
-        setAlertMessage(
-          'While importation the sources to elastic stack, unexpected error has been occurred.'
-        );
-        setSeverity('error');
-      }
+      // const kc_id = sessionStorage.getItem('userId');
+      // const source_id = source.id;
+      // const updatedSource = await updateSource(kc_id, source_id);
+      // if (updatedSource) {
+      //   setOpen(true);
+      //   setAlertMessage('Source imported to elastic stack successfully');
+      //   setSeverity('success');
+      //   await loadSources();
+      // } else {
+      //   setOpen(true);
+      //   setAlertMessage(
+      //     'While importation the sources to elastic stack, unexpected error has been occurred.'
+      //   );
+      //   setSeverity('error');
+      // }
     }
   };
 
@@ -387,8 +359,13 @@ const Sources = () => {
   ];
 
   const onFilePickerChange = async (files) => {
-    setFiles(files);
-    await handleSelectedFile(files);
+    if (files.length > 0) {
+      setFiles(files);
+      await handleSelectedFile(files);
+    } else {
+      setFiles([]);
+      setMetaUrfms([]);
+    }
   };
 
   const handleSelectedFile = async (files) => {
@@ -401,47 +378,24 @@ const Sources = () => {
 
   const handleData = (file) => {
     const { metadataRecords } = JSON.parse(file);
-
     if (metadataRecords) {
-      const columns = [];
-      const rows = [];
-
-      const prop = Object.keys(metadataRecords[0]);
-
-      prop.forEach((item) => {
-        const column = {
-          name: item,
-          options: {
-            display: true,
-          },
-        };
-        columns.push(column);
-      });
-
-      metadataRecords.forEach((row) => {
-        rows.push(row);
-      });
-
-      if (columns && rows) {
-        // setMetaUrfmsCol(columns)
-        setMetaUrfms(rows);
-      }
+      setMetaUrfms(metadataRecords);
     }
   };
 
-  const onSaveSource = async () => {
+  const onSaveSource = async (e) => {
+    e.preventDefault();
     if (nameValue && descriptionValue && metaUrfms) {
-      await globalActions.source.createSource(
-        metaUrfms,
-        nameValue,
-        descriptionValue,
-        sessionStorage.getItem('userId')
-      );
+      const result = await createSource(metaUrfms, nameValue, descriptionValue);
 
-      if (globalState.status === 'SUCCESS') {
+      if (result?.id) {
         setOpen(true);
         setAlertMessage('Source created.');
         setSeverity('success');
+        setNameValue('');
+        setDescriptionValue('');
+        setFiles([]);
+        setMetaUrfms([]);
 
         await loadSources();
       } else {
@@ -453,22 +407,30 @@ const Sources = () => {
   };
 
   const loadSources = useCallback(async () => {
-    if (sessionStorage.getItem('userId')) {
-      const user = await globalActions.user.findOneUserWithGroupAndRole(
-        sessionStorage.getItem('userId')
-      );
-      const role = user[0].roleid;
-      let result;
-      if (role === 1) {
-        result = await globalActions.source.allSources();
-      } else {
-        result = await globalActions.source.sources(sessionStorage.getItem('userId'));
-      }
-      if (result) {
-        setSources(result);
-      }
+    const userInfo = getUser();
+    const sub = userInfo.profile?.sub;
+    const user = await findUserBySub(sub);
+    const role = user.roles[0].role_id;
+    let result;
+    if (role === 1) {
+      result = await getSources();
+    } else {
+      result = await getSources();
+    }
+    if (result) {
+      result = result.map((source) => {
+        return {
+          id: source.id,
+          name: source.name,
+          description: source.description,
+          index_id: source.source_indices[0].index_id,
+          mng_id: source.source_indices[0].mng_id,
+          is_send: source.source_indices[0].is_send,
+        };
+      });
+      setSources(result);
     }
-  }, [globalActions.source, globalActions.user]);
+  }, [getSources, getUser, findUserBySub]);
 
   useEffect(() => {
     // clean up controller
@@ -499,7 +461,6 @@ const Sources = () => {
             setNameValue={setNameValue}
             descriptionValue={descriptionValue}
             setDescriptionValue={setDescriptionValue}
-            globalState={globalState}
             onFilePickerChange={onFilePickerChange}
             files={files}
             renderFiles={renderFiles}
@@ -527,24 +488,6 @@ const Sources = () => {
         </>
       ),
     },
-    {
-      id: 'tab3',
-      name: 'Share sources',
-      content: (
-        <>
-          <ShareSources />
-        </>
-      ),
-    },
-    {
-      id: 'tab4',
-      name: 'Shared sources',
-      content: (
-        <>
-          <SharedSources />
-        </>
-      ),
-    },
   ];
 
   const mergeModalForm = (
@@ -637,9 +580,6 @@ const Sources = () => {
               />
             </EuiForm>
           </EuiForm>
-          {globalState.isLoading && (
-            <EuiProgress postion="fixed" size="l" color="accent" />
-          )}
         </EuiPageContentBody>
       </EuiPageContent>
       {ShowAlert(open, handleClose, alertMessage, severity)}
diff --git a/src/pages/users/Users.js b/src/pages/users/Users.js
index 2ccf6fd..4910000 100644
--- a/src/pages/users/Users.js
+++ b/src/pages/users/Users.js
@@ -1,5 +1,4 @@
-import React, { useState, useCallback, useEffect, memo, useRef } from 'react';
-import store from '../../store/index';
+import React, { useState, useEffect, useCallback, memo, useRef } from 'react';
 import { ShowAlert } from '../../components/Common';
 import {
   EuiForm,
@@ -8,70 +7,10 @@ import {
   EuiPageContentHeaderSection,
   EuiTitle,
   EuiPageContentBody,
-  EuiTabbedContent,
   EuiFormRow,
-  EuiFieldText,
-  EuiFieldPassword,
-  EuiSelect,
-  EuiButton,
   EuiBasicTable,
 } from '@elastic/eui';
-
-const NewUserForm = memo(
-  ({
-    globalState,
-    usernameValue,
-    setUsername,
-    passwordValue,
-    setPasswordValue,
-    email,
-    setEmail,
-    roles,
-    selectedRole,
-    setSelectedRole,
-    onSaveUser,
-  }) => {
-    return (
-      <>
-        <EuiForm component="form">
-          <EuiFormRow label="Username">
-            <EuiFieldText
-              value={usernameValue}
-              onChange={(e) => setUsername(e.target.value)}
-            />
-          </EuiFormRow>
-          <EuiFormRow label="Password">
-            <EuiFieldPassword
-              fullWidth
-              placeholder="Password"
-              type={'dual'}
-              value={passwordValue}
-              onChange={(e) => setPasswordValue(e.target.value)}
-              aria-label="Use aria labels when no actual label is in use"
-            />
-          </EuiFormRow>
-          <EuiFormRow label="e-mail">
-            <EuiFieldText value={email} onChange={(e) => setEmail(e.target.value)} />
-          </EuiFormRow>
-          <EuiFormRow label="Select specific roles">
-            <EuiSelect
-              options={roles}
-              value={selectedRole}
-              onChange={(e) => setSelectedRole(e.target.value)}
-            />
-          </EuiFormRow>
-          <EuiFormRow label="">
-            {
-              <EuiButton fill onClick={onSaveUser} isLoading={globalState.isLoading}>
-                Save
-              </EuiButton>
-            }
-          </EuiFormRow>
-        </EuiForm>
-      </>
-    );
-  }
-);
+import { getUsers, deleteUser } from '../../services/GatekeeperService';
 
 const UserList = memo(
   ({ users, userColumns, onTableChange, tableRef, pagination, sorting }) => {
@@ -88,7 +27,6 @@ const UserList = memo(
               ref={tableRef}
               pagination={pagination}
               sorting={sorting}
-              // selection={selection}
             />
           </EuiFormRow>
         </EuiForm>
@@ -98,17 +36,10 @@ const UserList = memo(
 );
 
 const Users = () => {
-  const [globalState, globalActions] = store();
-  const [selectedTabNumber, setSelectedTabNumber] = useState(0);
   const [open, setOpen] = useState(false);
   const [alertMessage, setAlertMessage] = useState('');
   const [severity, setSeverity] = useState('info');
-  const [dual] = useState(true);
-  const [passwordValue, setPasswordValue] = useState('');
-  const [usernameValue, setUsername] = useState('');
-  const [email, setEmail] = useState('');
-  const [roles, setRoles] = useState([{ value: 0, text: 'select a role' }]);
-  const [selectedRole, setSelectedRole] = useState();
+
   const [users, setUsers] = useState([]);
   const [sortDirection, setSortDirection] = useState('asc');
   const [sortField, setSortField] = useState('username');
@@ -116,69 +47,46 @@ const Users = () => {
   const [pageIndex, setPageIndex] = useState(0);
   const [pageSize, setPageSize] = useState(5);
 
-  const loadRoles = useCallback(async () => {
-    const _roles = [];
-    const roles = await globalActions.user.findRole();
-    if (roles) {
-      for (const role of roles) {
-        _roles.push({ value: role.id, text: role.name });
-      }
-    }
-    setRoles((prevRoles) => [...prevRoles, ..._roles]);
-  }, [globalActions.user]);
-
   const loadUsers = useCallback(async () => {
-    const users = await globalActions.user.usersWithGroupAndRole();
-
-    if (users) {
-      const userList = [];
-      const userNameList = [];
-      users.forEach((user) => {
-        if (userNameList.includes(user.username)) {
-          userList[userNameList.indexOf(user.username)].groupname =
-            `${userList[userNameList.indexOf(user.username)].groupname}, ${user.groupname}`;
-        } else {
-          userNameList.push(user.username);
-          userList.push(user);
-        }
+    const response = await getUsers();
+    if (response) {
+      const users = response.map((user) => {
+        return {
+          id: user.kc_id,
+          email: user.email,
+          groupname: user.groups
+            .map((element) => {
+              const { group } = element;
+              return group.name;
+            })
+            .join(', '),
+          rolename: user.roles.map((element) => {
+            const { role } = element;
+            return role.name;
+          }),
+        };
       });
-      setUsers(userList);
+      setUsers(users);
     }
-  }, [globalActions.user]);
+  }, [getUsers]);
 
   useEffect(() => {
-    // clean up controller
-    let isSubscribed = true;
-    if (isSubscribed) {
-      loadRoles();
-      loadUsers();
-    }
-    // cancel subscription to useEffect
-    return () => (isSubscribed = false);
-  }, [loadRoles, loadUsers]);
-
-  const onSaveUser = async () => {
-    if (usernameValue && passwordValue && email && selectedRole) {
-      await globalActions.user.createUser(
-        usernameValue,
-        email,
-        passwordValue,
-        selectedRole
-      );
-      setOpen(true);
-      setAlertMessage('User has been created.');
-      setSeverity('success');
-      loadUsers();
-    }
-  };
-
-  const onDeleteUser = async (user) => {
-    if (user) {
-      await globalActions.user.deleteUser(user.kc_id);
-      setOpen(true);
-      setAlertMessage('Users has been deleted.');
-      setSeverity('success');
-      await loadUsers();
+    loadUsers();
+  }, [loadUsers]);
+
+  const onDeleteUser = async (id) => {
+    if (id) {
+      const response = await deleteUser(id);
+      if (!response) {
+        setAlertMessage('User has not been deleted.');
+        setSeverity('error');
+        setOpen(true);
+      } else {
+        setAlertMessage('User has been deleted.');
+        setSeverity('success');
+        setOpen(true);
+        await loadUsers();
+      }
     }
   };
 
@@ -189,20 +97,12 @@ const Users = () => {
       icon: 'trash',
       type: 'icon',
       color: 'danger',
-      onClick: onDeleteUser,
+      onClick: async (user) => {
+        onDeleteUser(user.id);
+      },
     },
   ];
 
-  const onTableChange = ({ page = {}, sort = {} }) => {
-    const { index: pageIndex, size: pageSize } = page;
-
-    const { field: sortField, direction: sortDirection } = sort;
-
-    setPageIndex(pageIndex);
-    setPageSize(pageSize);
-    setSortField(sortField);
-    setSortDirection(sortDirection);
-  };
   const totalItemCount = typeof USERS === typeof undefined ? 0 : users.length;
 
   const pagination = {
@@ -220,56 +120,22 @@ const Users = () => {
   };
 
   const userColumns = [
-    { field: 'username', name: 'Username' },
     { field: 'email', name: 'Email' },
-    { field: 'groupname', name: 'Group' },
-    { field: 'rolename', name: 'Role' },
-    { field: 'roledescription', name: 'Role description' },
+    { field: 'groupname', name: 'Groups' },
+    { field: 'rolename', name: 'Roles' },
     { name: 'Actions', actions: userActions },
   ];
 
-  const tabContents = [
-    {
-      id: 'tab1',
-      name: 'New user',
-      content: (
-        <>
-          <br />
-          <NewUserForm
-            globalState={globalState}
-            dual={dual}
-            usernameValue={usernameValue}
-            setUsername={setUsername}
-            passwordValue={passwordValue}
-            setPasswordValue={setPasswordValue}
-            email={email}
-            setEmail={setEmail}
-            onSaveUser={onSaveUser}
-            selectedRole={selectedRole}
-            setSelectedRole={setSelectedRole}
-            roles={roles}
-          />
-        </>
-      ),
-    },
-    {
-      id: 'tab2',
-      name: 'Users list',
-      content: (
-        <>
-          <br />
-          <UserList
-            users={users}
-            userColumns={userColumns}
-            onTableChange={onTableChange}
-            tableRef={tableRef}
-            pagination={pagination}
-            sorting={sorting}
-          />
-        </>
-      ),
-    },
-  ];
+  const onTableChange = ({ page = {}, sort = {} }) => {
+    const { index: pageIndex, size: pageSize } = page;
+
+    const { field: sortField, direction: sortDirection } = sort;
+
+    setPageIndex(pageIndex);
+    setPageSize(pageSize);
+    setSortField(sortField);
+    setSortDirection(sortDirection);
+  };
 
   const handleClose = (event, reason) => {
     if (reason === 'clickaway') {
@@ -289,12 +155,13 @@ const Users = () => {
         </EuiPageContentHeader>
         <EuiPageContentBody>
           <EuiForm>
-            <EuiTabbedContent
-              tabs={tabContents}
-              selectedTab={tabContents[selectedTabNumber]}
-              onTabClick={(tab) => {
-                setSelectedTabNumber(tabContents.indexOf(tab));
-              }}
+            <UserList
+              users={users}
+              userColumns={userColumns}
+              onTableChange={onTableChange}
+              tableRef={tableRef}
+              pagination={pagination}
+              sorting={sorting}
             />
           </EuiForm>
         </EuiPageContentBody>
diff --git a/src/services/GatekeeperService.js b/src/services/GatekeeperService.js
new file mode 100644
index 0000000..3563f9b
--- /dev/null
+++ b/src/services/GatekeeperService.js
@@ -0,0 +1,374 @@
+import { User, UserManager, WebStorageStateStore } from 'oidc-client-ts';
+
+export const userManager = new UserManager({
+  authority: process.env.REACT_APP_KEYCLOAK_BASE_URL,
+  client_id: process.env.REACT_APP_KEYCLOAK_CLIENT_ID,
+  client_secret: process.env.REACT_APP_KEYCLOAK_CLIENT_SECRET,
+  redirect_uri: process.env.REACT_APP_BASE_URL,
+  userStore: new WebStorageStateStore({ store: window.localStorage }),
+});
+
+export function getUser() {
+  const oidcStorage = localStorage.getItem(
+    `oidc.user:${process.env.REACT_APP_KEYCLOAK_BASE_URL}:${process.env.REACT_APP_KEYCLOAK_CLIENT_ID}`
+  );
+  if (!oidcStorage) {
+    return null;
+  }
+
+  return User.fromStorageString(oidcStorage);
+}
+
+const get = async (path, payload) => {
+  const user = getUser();
+  const access_token = user?.access_token;
+  const headers = {
+    'Content-Type': 'application/json',
+    Authorization: `Bearer ${access_token}`,
+  };
+  const response = await fetch(`${process.env.REACT_APP_GATEKEEPER_BASE_URL}${path}`, {
+    method: 'GET',
+    headers,
+    mode: 'cors',
+    body: JSON.stringify(payload),
+  });
+  if (response.status === 401) {
+    try {
+      await userManager.signinSilent();
+      return await this.get(path, payload);
+    } catch (error) {
+      const currentHash = window.location.hash;
+      await userManager.signoutRedirect({
+        post_logout_redirect_uri: `${process.env.REACT_APP_BASE_URL}${currentHash}`,
+      });
+    }
+  }
+  return await response.json();
+};
+
+const post = async (path, payload) => {
+  const user = getUser();
+  const access_token = user?.access_token;
+  const headers = {
+    'Content-Type': 'application/json',
+    Authorization: `Bearer ${access_token}`,
+  };
+  const response = await fetch(`${process.env.REACT_APP_GATEKEEPER_BASE_URL}${path}`, {
+    method: 'POST',
+    headers,
+    body: JSON.stringify(payload),
+    mode: 'cors',
+  });
+  if (response.status === 401) {
+    try {
+      await userManager.signinSilent();
+      return await this.post(path, payload);
+    } catch (error) {
+      const currentHash = window.location.hash;
+      await userManager.signoutRedirect({
+        post_logout_redirect_uri: `${process.env.REACT_APP_BASE_URL}${currentHash}`,
+      });
+    }
+  }
+  return await response.json();
+};
+
+const deleteRequest = async (path, payload) => {
+  const user = getUser();
+  const access_token = user?.access_token;
+  const headers = {
+    'Content-Type': 'application/json',
+    Authorization: `Bearer ${access_token}`,
+  };
+  const response = await fetch(`${process.env.REACT_APP_GATEKEEPER_BASE_URL}${path}`, {
+    method: 'DELETE',
+    headers,
+    body: JSON.stringify(payload),
+    mode: 'cors',
+  });
+  if (response.status === 401) {
+    try {
+      await userManager.signinSilent();
+      return await this.post(path, payload);
+    } catch (error) {
+      const currentHash = window.location.hash;
+      await userManager.signoutRedirect({
+        post_logout_redirect_uri: `${process.env.REACT_APP_BASE_URL}${currentHash}`,
+      });
+    }
+  }
+  if (response.status === 204) {
+    return {
+      success: true,
+      message: 'Request deleted successfully',
+    };
+  } else {
+    return {
+      success: false,
+      message: 'Request not deleted',
+    };
+  }
+};
+
+export const createUser = async (sub, email) => {
+  const path = `/users`;
+  return await post(path, {
+    kc_id: sub,
+    email,
+  });
+};
+
+export const deleteUser = async (sub) => {
+  const path = `/users/${sub}`;
+  return await deleteRequest(path, {});
+};
+
+export const getUsers = async () => {
+  const path = `/users`;
+  return await get(path);
+};
+
+export const findUserBySub = async (sub) => {
+  const path = `/users/${sub}`;
+  return await get(path);
+};
+
+export const getRoles = async () => {
+  const path = `/roles`;
+  return await get(path);
+};
+
+export const createRole = async (name, description) => {
+  const path = `/roles`;
+  return await post(path, {
+    name: name,
+    description: description,
+  });
+};
+
+export const addUserToRole = async (sub, role_id) => {
+  const path = `/roles/${role_id}/users`;
+  return await post(path, {
+    kc_id: sub,
+  });
+};
+
+export const removeUserFromRole = async (sub, role_id) => {
+  const path = `/roles/${role_id}/users/${sub}`;
+  return await deleteRequest(path, {});
+};
+
+export const deleteRole = async (id) => {
+  const path = `/roles/${id}`;
+  return await deleteRequest(path, {});
+};
+
+export const createUserRequest = async (message, sub) => {
+  const path = `/users/${sub}/requests`;
+  return await post(path, {
+    message: message,
+  });
+};
+
+export const deleteUserRequest = async (id) => {
+  const path = `/user-requests/${id}`;
+  return await deleteRequest(path, {});
+};
+
+export const getGroups = async () => {
+  const path = `/groups`;
+  return await get(path);
+};
+
+export const createGroup = async (name, description) => {
+  const path = `/groups`;
+  const user = getUser();
+  const sub = user?.profile?.sub;
+  return await post(path, {
+    kc_id: sub,
+    name: name,
+    description: description,
+  });
+};
+
+export const deleteGroup = async (id) => {
+  const path = `/groups/${id}`;
+  return await deleteRequest(path, {});
+};
+
+export const addUserToGroup = async (sub, group_id) => {
+  const path = `/groups/${group_id}/users`;
+  return await post(path, {
+    kc_id: sub,
+  });
+};
+
+export const removeUserFromGroup = async (sub, group_id) => {
+  const path = `/groups/${group_id}/users/${sub}`;
+  return await deleteRequest(path, {});
+};
+
+export const getUserFieldsDisplaySettings = async (sub) => {
+  const path = `/users/${sub}/fields`;
+  return await get(path);
+};
+
+export const setUserFieldsDisplaySettings = async (sub, fields) => {
+  const path = `/users/${sub}/fields`;
+  return await post(path, {
+    fields_id: fields,
+  });
+};
+
+export const createSource = async (metaUrfms, name, description) => {
+  const path = `/sources`;
+  const user = getUser();
+  const sub = user.profile?.sub;
+  return await post(path, {
+    name: name,
+    description: description,
+    metaUrfms: metaUrfms,
+    kc_id: sub,
+  });
+};
+
+export const getSources = async () => {
+  const path = `/sources`;
+  return await get(path);
+};
+
+export const deleteSource = async (source_id) => {
+  const path = `/sources/${source_id}`;
+  return await deleteRequest(path, {});
+};
+
+export const getRequests = async () => {
+  const path = `/user-requests`;
+  return await get(path);
+};
+
+export const getPendingRequests = async () => {
+  const path = `/user-requests/pending`;
+  return await get(path);
+};
+
+export const deleteRequestById = async (id) => {
+  const path = `/user-requests/${id}`;
+  return await deleteRequest(path, {});
+};
+
+export const updateUserRequest = async (id, is_processed) => {
+  const path = `/user-requests/${id}`;
+  return await post(path, {
+    is_processed: is_processed,
+  });
+};
+
+export const getStdFields = async () => {
+  const path = `/std_fields`;
+  return await get(path);
+};
+
+export const createStdField = async (
+  cardinality,
+  category,
+  definition_and_comment,
+  field_name,
+  field_type,
+  is_optional,
+  is_public,
+  obligation_or_condition,
+  values,
+  list_url,
+  default_display_fields
+) => {
+  const path = `/std_fields`;
+  return await post(path, {
+    cardinality,
+    category,
+    definition_and_comment,
+    field_name,
+    field_type,
+    isoptional: is_optional,
+    ispublic: is_public,
+    obligation_or_condition,
+    values,
+    list_url,
+    default_display_fields
+  });
+};
+
+export const addFieldToPolicy = async (field_id, policy_id) => {
+  const path = `/policies/${policy_id}/std_fields`;
+  return await post(path, {
+    field_id,
+  });
+};
+
+export const removeFieldFromPolicy = async (field_id, policy_id) => {
+  const path = `/policies/${policy_id}/std_fields/${field_id}`;
+  return await deleteRequest(path, {});
+};
+
+export const deleteAllStdFields = async () => {
+  const path = `/std_fields`;
+  return await deleteRequest(path, {});
+};
+
+export const getPublicFields = async () => {
+  const path = `/public_std_fields`;
+  return await get(path);
+};
+
+export const createPolicy = async (name) => {
+  const path = `/policies`;
+  const kc_id = getUser().profile?.sub;
+  return await post(path, {
+    name,
+    kc_id,
+  });
+};
+
+export const addSourceToPolicy = async (source_id, policy_id) => {
+  const path = `/policies/${policy_id}/sources`;
+  return await post(path, {
+    source_id,
+  });
+};
+
+export const removeSourceFromPolicy = async (source_id, policy_id) => {
+  const path = `/policies/${policy_id}/sources/${source_id}`;
+  return await deleteRequest(path, {});
+};
+
+export const addPolicyToGroup = async (policy_id, group_id) => {
+  const path = `/groups/${group_id}/policies`;
+  return await post(path, {
+    policy_id,
+  });
+};
+
+export const removePolicyFromGroup = async (policy_id, group_id) => {
+  const path = `/groups/${group_id}/policies/${policy_id}`;
+  return await deleteRequest(path, {});
+};
+
+export const deletePolicy = async (id) => {
+  const path = `/policies/${id}`;
+  return await deleteRequest(path, {});
+};
+
+export const getPolicies = async () => {
+  const path = `/policies`;
+  return await get(path);
+};
+
+export const getUserPolicies = async (sub) => {
+  const path = `/users/${sub}/policies`;
+  return await get(path);
+};
+
+export const searchQuery = async (payload) => {
+  const path = `/search`;
+  return await post(path, payload);
+};
diff --git a/src/store/CustomConnector.js b/src/store/CustomConnector.js
deleted file mode 100644
index 28b24ca..0000000
--- a/src/store/CustomConnector.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import React, { Component } from 'react';
-
-export const CustomConnectorContext = React.createContext();
-
-export class CustomConnectorProvider extends Component {
-  render() {
-    return (
-      <CustomConnectorContext.Provider value={this.props.dataStore}>
-        {this.props.children}
-      </CustomConnectorContext.Provider>
-    );
-  }
-}
-
-export class CustomConnector extends React.Component {
-  static contextType = CustomConnectorContext;
-
-  constructor(props, context) {
-    super(props, context);
-    this.state = this.selectData();
-    this.functionProps = Object.entries(this.props.dispatchers)
-      .map(([k, v]) => [k, (...args) => this.context.dispatch(v(...args))])
-      .reduce((result, [k, v]) => ({ ...result, [k]: v }), {});
-  }
-
-  render() {
-    return React.Children.map(this.props.children, (c) =>
-      React.cloneElement(c, { ...this.state, ...this.functionProps })
-    );
-  }
-
-  selectData() {
-    let storeState = this.context.getState();
-    return Object.entries(this.props.selectors)
-      .map(([k, v]) => [k, v(storeState)])
-      .reduce((result, [k, v]) => ({ ...result, [k]: v }), {});
-  }
-
-  handleDataStoreChange() {
-    let newData = this.selectData();
-    Object.keys(this.props.selectors)
-      .filter((key) => this.state[key] !== newData[key])
-      .forEach((key) => this.setState({ [key]: newData[key] }));
-  }
-
-  componentDidMount() {
-    this.unsubscriber = this.context.subscribe(() => this.handleDataStoreChange());
-  }
-
-  componentWillUnmount() {
-    this.unsubscriber();
-  }
-}
diff --git a/src/store/asyncEnhancer.js b/src/store/asyncEnhancer.js
deleted file mode 100644
index 7f9e47e..0000000
--- a/src/store/asyncEnhancer.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export const asyncEnhancer =
-  (delay) =>
-  (createStoreFunction) =>
-  (...args) => {
-    const store = createStoreFunction(...args);
-    return {
-      ...store,
-      dispatchAsync: (action) =>
-        new Promise((resolve, reject) => {
-          setTimeout(() => {
-            store.dispatch(action);
-            resolve();
-          }, delay);
-        }),
-    };
-  };
diff --git a/src/store/index.js b/src/store/index.js
deleted file mode 100644
index 905e71e..0000000
--- a/src/store/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from 'react';
-import useStore from './useStore';
-import * as actions from '../actions';
-
-const initialState = {
-  isLoading: false,
-  status: 'INITIAL',
-  users: [],
-  roles: [],
-  role: {},
-  user: {},
-  allocatedRoles: [],
-  error: false,
-  resources: [],
-};
-const store = useStore(React, initialState, actions);
-export default store;
diff --git a/src/store/useStore.js b/src/store/useStore.js
deleted file mode 100644
index bb16c7e..0000000
--- a/src/store/useStore.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useSessionStorage } from '@in-sylva/react-use-storage';
-
-function setState(store, newState, afterUpdateCallback) {
-  store.state = { ...store.state, ...newState };
-  store.listeners.forEach((listener) => {
-    listener.run(store.state);
-  });
-  afterUpdateCallback && afterUpdateCallback();
-}
-
-function useCustom(store, React, mapState, mapActions) {
-  const [, originalHook] = useSessionStorage('portal', Object.create(null));
-  const state = mapState ? mapState(store.state) : store.state;
-  const actions = React.useMemo(
-    () => (mapActions ? mapActions(store.actions) : store.actions),
-    [mapActions, store.actions]
-  );
-
-  React.useEffect(() => {
-    const newListener = { oldState: {} };
-    newListener.run = mapState
-      ? (newState) => {
-          const mappedState = mapState(newState);
-          if (mappedState !== newListener.oldState) {
-            newListener.oldState = mappedState;
-            originalHook(mappedState);
-          }
-        }
-      : originalHook;
-    store.listeners.push(newListener);
-    newListener.run(store.state);
-    return () => {
-      store.listeners = store.listeners.filter((listener) => listener !== newListener);
-    };
-  }, []); // eslint-disable-line
-  return [state, actions];
-}
-
-function associateActions(store, actions) {
-  const associatedActions = {};
-  Object.keys(actions).forEach((key) => {
-    if (typeof actions[key] === 'function') {
-      associatedActions[key] = actions[key].bind(null, store);
-    }
-    if (typeof actions[key] === 'object') {
-      associatedActions[key] = associateActions(store, actions[key]);
-    }
-  });
-  return associatedActions;
-}
-
-const useStore = (React, initialState, actions, initializer) => {
-  const store = { state: initialState, listeners: [] };
-  store.setState = setState.bind(null, store);
-  store.actions = associateActions(store, actions);
-  if (initializer) initializer(store);
-  return useCustom.bind(null, store, React);
-};
-
-export default useStore;
diff --git a/src/utils.js b/src/utils.js
index 9ad2ab2..6b39314 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,39 +1,5 @@
-import { EuiIcon } from '@elastic/eui';
 import React from 'react';
-
-export const getGatekeeperBaseUrl = () => {
-  return process.env.REACT_APP_IN_SYLVA_GATEKEEPER_PORT
-    ? `${process.env.REACT_APP_IN_SYLVA_GATEKEEPER_HOST}:${process.env.REACT_APP_IN_SYLVA_GATEKEEPER_PORT}`
-    : `${window._env_.REACT_APP_IN_SYLVA_GATEKEEPER_HOST}`;
-};
-
-export const getLoginUrl = () => {
-  return process.env.REACT_APP_IN_SYLVA_LOGIN_PORT
-    ? `${process.env.REACT_APP_IN_SYLVA_LOGIN_HOST}:${process.env.REACT_APP_IN_SYLVA_LOGIN_PORT}`
-    : `${window._env_.REACT_APP_IN_SYLVA_LOGIN_HOST}`;
-};
-
-export const redirect = (url, condition = true) => {
-  if (condition) {
-    window.location.replace(url);
-  }
-};
-
-export const getUrlParam = (parameter, defaultValue) => {
-  let urlParameter = defaultValue;
-  if (window.location.href.indexOf(parameter) > -1) {
-    urlParameter = getUrlParams()[parameter];
-  }
-  return urlParameter;
-};
-
-export const getUrlParams = () => {
-  let lets = {};
-  window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
-    lets[key] = value;
-  });
-  return lets;
-};
+import { EuiIcon } from '@elastic/eui';
 
 // Function used to mock statistics for dashboard page
 export const getRandomData = (arrayLength) => {
@@ -44,11 +10,19 @@ export const getRandomData = (arrayLength) => {
     });
 };
 
-export const getUserRoleId = () => {
-  if (sessionStorage.getItem('roleId').split('#')[0]) {
-    return parseInt(sessionStorage.getItem('roleId').split('#')[0]);
-  } else {
-    return parseInt(sessionStorage.getItem('roleId'));
+export const safeJsonStringify = (str) => {
+  try {
+    return JSON.stringify(str);
+  } catch (e) {
+    return null;
+  }
+};
+
+export const safeJsonParse = (str) => {
+  try {
+    return JSON.parse(str);
+  } catch (e) {
+    return null;
   }
 };
 
@@ -56,70 +30,66 @@ export const getSideBarItems = () => {
   return [
     {
       id: 0,
+      label: 'Home',
+      link: '/home',
+      roles: [1, 2, 3],
+      icon: <EuiIcon type="home" size="l" />,
+    },
+    {
+      id: 1,
       label: 'Dashboard',
-      link: '/app/dashboard',
+      link: '/dashboard',
       roles: [1],
       icon: <EuiIcon type="dashboardApp" size="l" />,
     },
     {
-      id: 1,
+      id: 2,
       label: 'Users',
-      link: '/app/users',
+      link: '/users',
       roles: [1],
       icon: <EuiIcon type="user" size="l" />,
     },
     {
-      id: 2,
+      id: 3,
       label: 'Users roles',
-      link: '/app/roles',
+      link: '/roles',
       roles: [1],
       icon: <EuiIcon type="usersRolesApp" size="l" />,
     },
     {
-      id: 3,
+      id: 4,
       label: 'Groups',
-      link: '/app/groups',
+      link: '/groups',
       roles: [1],
       icon: <EuiIcon type="users" size="l" />,
     },
     {
-      id: 4,
+      id: 5,
       label: 'Requests',
-      link: '/app/requests',
+      link: '/requests',
       roles: [1],
       icon: <EuiIcon type="email" size="l" />,
     },
     {
-      id: 5,
+      id: 6,
       label: 'Policies',
-      link: '/app/policies',
-      roles: [1, 2],
+      link: '/policies',
+      roles: [1],
       icon: <EuiIcon type="lockOpen" size="l" />,
     },
     {
-      id: 6,
+      id: 7,
       label: 'Sources',
-      link: '/app/sources',
+      link: '/sources',
       roles: [1, 2],
       icon: <EuiIcon type="indexManagementApp" size="l" />,
     },
     {
-      id: 7,
+      id: 8,
       label: 'Fields',
-      link: '/app/fields',
-      roles: [1],
+      link: '/fields',
+      roles: [1, 2],
       icon: <EuiIcon type="visTable" size="l" />,
     },
   ];
 };
-
-export const changeNameToLabel = (object) => {
-  object.label = object.name;
-  delete object.name;
-  return object;
-};
-
-export const tokenTimedOut = (validityDurationInMin) => {
-  const timeSinceLastRefresh = Date.now() - sessionStorage.getItem('token_refresh_time');
-  return timeSinceLastRefresh > validityDurationInMin * 60000;
-};
-- 
GitLab