From c30186778dfffda866483049f564d9046fc479f9 Mon Sep 17 00:00:00 2001
From: behnamrhp <behnamrahimpour74@gmail.com>
Date: Mon, 22 May 2023 21:26:45 +0300
Subject: [PATCH] [FEAT]: add accesstoken interceptor

---
 .env.development                              |  1 +
 .../auth-admin-login/authAdminLogin.ts        | 16 +++-
 .../authAdminPhoneNumberDriven.ts             | 16 +++-
 .../createAccountAdapter.ts                   | 16 +++-
 .../createProfileAdapter.ts                   | 16 +++-
 .../get-places-adapter/getPlacesAdapter.ts    | 16 +++-
 .../get-users-adapter/getUsersAdapter.ts      | 16 +++-
 .../boundaries/http-boundary/httpBoundary.ts  | 88 ++++++++++++++++---
 src/driven/utils/configs/appConfig.ts         |  1 +
 src/driven/utils/constants/envs.ts            |  1 +
 .../utils/helpers/contexts/userContext.tsx    |  2 +-
 src/driven/utils/helpers/globalHelpers.ts     | 22 +++++
 .../getNavigatorAndAccessTokenUpdator.ts      | 24 +++++
 .../core/common/table-row/view/TableRow.tsx   | 10 ++-
 .../core/create-user/infra/CreateUser.tsx     | 17 +++-
 .../core/places-list/infra/PlacesList.tsx     |  7 +-
 .../core/users-list/infra/UsersList.tsx       | 11 ++-
 .../authentication/infra/Authentication.tsx   |  8 +-
 .../main/pages/layouts/MainPageLayout.tsx     |  2 +-
 .../main/pages/layouts/UserLoginLayout.tsx    |  4 +-
 20 files changed, 258 insertions(+), 36 deletions(-)
 create mode 100644 src/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator.ts

diff --git a/.env.development b/.env.development
index 679bd12..ff1bac7 100644
--- a/.env.development
+++ b/.env.development
@@ -2,6 +2,7 @@ VITE_API_ORIGIN = https://admin.dev.dipal.ru/api/v1
 VITE_API_AUTH_ORIGIN = https://auth.dev.dipal.ru/api/v1/auth
 VITE_API_AUTH_PHONENUMBER = /start-challenge
 VITE_API_AUTH_LOGIN = /login
+VITE_API_AUTH_REFRESH = /refresh-token
 VITE_API_PLACES = /place
 VITE_API_USERS = /profile
 VITE_API_USERS_ACCOUNT = /account
diff --git a/src/driven/adapters/auth-admin-login/authAdminLogin.ts b/src/driven/adapters/auth-admin-login/authAdminLogin.ts
index 195a3a3..c5d2f8d 100644
--- a/src/driven/adapters/auth-admin-login/authAdminLogin.ts
+++ b/src/driven/adapters/auth-admin-login/authAdminLogin.ts
@@ -4,9 +4,21 @@ import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
 import { IOtpAuthDrivenPort } from '~/business-logic/generic/admin-user/authentication/otp-auth/port';
 import { OtpAuthResponse } from '~/business-logic/generic/admin-user/authentication/otp-auth/data/reponse-object/otpAuthRO';
 import { OtpAuthDTOReturnType } from '~/business-logic/generic/admin-user/authentication/otp-auth/data/dto/otpAuthDto';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 
-const authAdminLogin = (): IOtpAuthDrivenPort => {
-  const httpProvider = new HTTPPovider();
+const authAdminLogin = (
+  userAdmin: AdminUserModel | null,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): IOtpAuthDrivenPort => {
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin && userAdmin.adminUserData.accessToken && null,
+      refreshToken: userAdmin && userAdmin.adminUserData.refreshToken && null,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
   const httpHandler = (data: OtpAuthDTOReturnType): Promise<OtpAuthResponse> => {
     const url = apiUrls.generic.authLogin;
     const options: HttpOptionsType = {
diff --git a/src/driven/adapters/auth-admin-phonenumber/authAdminPhoneNumberDriven.ts b/src/driven/adapters/auth-admin-phonenumber/authAdminPhoneNumberDriven.ts
index 11b0e09..c708240 100644
--- a/src/driven/adapters/auth-admin-phonenumber/authAdminPhoneNumberDriven.ts
+++ b/src/driven/adapters/auth-admin-phonenumber/authAdminPhoneNumberDriven.ts
@@ -4,12 +4,24 @@ import { PhonenumberAuthDTOReturnType } from '~/business-logic/generic/admin-use
 import { IPhonenumberAuthPort } from '~/business-logic/generic/admin-user/authentication/phonnumber-auth/port';
 import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
 import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 
-const authAdminPhoneNumberDriven = (): IPhonenumberAuthPort => {
+const authAdminPhoneNumberDriven = (
+  userAdmin: AdminUserModel | null,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): IPhonenumberAuthPort => {
   // make http handler ready for the phone number
   const wrongPhoneNumberMessage = staticMessages.global.errors.phonenumber;
 
-  const httpProvider = new HTTPPovider();
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin && userAdmin?.adminUserData.accessToken && null,
+      refreshToken: userAdmin && userAdmin?.adminUserData.refreshToken && null,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
   const httpHandler = (data: PhonenumberAuthDTOReturnType) => {
     const url = apiUrls.generic.authPhonenumber;
     const options: HttpOptionsType = {
diff --git a/src/driven/adapters/create-account-adapter/createAccountAdapter.ts b/src/driven/adapters/create-account-adapter/createAccountAdapter.ts
index 063bf86..b16bc97 100644
--- a/src/driven/adapters/create-account-adapter/createAccountAdapter.ts
+++ b/src/driven/adapters/create-account-adapter/createAccountAdapter.ts
@@ -1,15 +1,27 @@
 import { INewUserData } from '~/business-logic/core/users/create-user/create-account/data/dto/protocols';
 import { CreateAcountResponseApi } from '~/business-logic/core/users/create-user/create-account/data/response-object/protocols';
 import createUserPort from '~/business-logic/core/users/create-user/ports';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
 import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
 import { apiUrls } from '~/driven/utils/configs/appConfig';
 
-const createAccountAdapter = (): createUserPort['httpAccountHandler'] => {
+const createAccountAdapter = (
+  userAdmin: AdminUserModel,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): createUserPort['httpAccountHandler'] => {
   // make url
   const url = apiUrls.core.createUserAccount;
   // call http provider
-  const httpProvider = new HTTPPovider();
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin.adminUserData.accessToken,
+      refreshToken: userAdmin.adminUserData.refreshToken,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
 
   const httpHandler = (newUserData: INewUserData) => {
     // api options
diff --git a/src/driven/adapters/create-profile-adapter/createProfileAdapter.ts b/src/driven/adapters/create-profile-adapter/createProfileAdapter.ts
index 47e3901..32afa07 100644
--- a/src/driven/adapters/create-profile-adapter/createProfileAdapter.ts
+++ b/src/driven/adapters/create-profile-adapter/createProfileAdapter.ts
@@ -1,14 +1,26 @@
 import { CreateProfileDtoReturnType } from '~/business-logic/core/users/create-user/create-profile/data/dto/protocols';
 import createUserPort from '~/business-logic/core/users/create-user/ports';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
 import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
 import { apiUrls } from '~/driven/utils/configs/appConfig';
 
-const createProfileAdapter = (): createUserPort['httpProfileHandler'] => {
+const createProfileAdapter = (
+  userAdmin: AdminUserModel,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): createUserPort['httpProfileHandler'] => {
   // make url
   const url = apiUrls.core.createUserProfile;
   // call http provider
-  const httpProvider = new HTTPPovider();
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin.adminUserData.accessToken,
+      refreshToken: userAdmin.adminUserData.refreshToken,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
 
   const httpHandler = (newAccountData: CreateProfileDtoReturnType) => {
     // api options
diff --git a/src/driven/adapters/get-places-adapter/getPlacesAdapter.ts b/src/driven/adapters/get-places-adapter/getPlacesAdapter.ts
index f48df14..5d6b52c 100644
--- a/src/driven/adapters/get-places-adapter/getPlacesAdapter.ts
+++ b/src/driven/adapters/get-places-adapter/getPlacesAdapter.ts
@@ -3,9 +3,14 @@ import IGetPlacesPort from '~/business-logic/core/places/get-places/port';
 import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
 import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
 import { apiUrls } from '~/driven/utils/configs/appConfig';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import { getPlacesAdapterReturnType } from './protocols';
 
-const getPlacesAdapter = (): IGetPlacesPort & getPlacesAdapterReturnType => {
+const getPlacesAdapter = (
+  userAdmin: AdminUserModel,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): IGetPlacesPort & getPlacesAdapterReturnType => {
   // url of api
   const url = apiUrls.core.getPlaces;
   // make the options of request
@@ -14,7 +19,14 @@ const getPlacesAdapter = (): IGetPlacesPort & getPlacesAdapterReturnType => {
     method: 'GET',
   };
   // make the httpHandler
-  const httpProvider = new HTTPPovider();
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin.adminUserData.accessToken,
+      refreshToken: userAdmin.adminUserData.refreshToken,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
 
   const httpHandler = async () => httpProvider.request<GetPlacesResponse>(options);
 
diff --git a/src/driven/adapters/get-users-adapter/getUsersAdapter.ts b/src/driven/adapters/get-users-adapter/getUsersAdapter.ts
index d22f23e..e46541f 100644
--- a/src/driven/adapters/get-users-adapter/getUsersAdapter.ts
+++ b/src/driven/adapters/get-users-adapter/getUsersAdapter.ts
@@ -3,9 +3,14 @@ import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
 import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
 import { GetUsersResponse } from '~/business-logic/core/users/get-users/data/response-object/protocols';
 import IGetUsersPort from '~/business-logic/core/users/get-users/ports';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import { getUsersAdapterReturnType } from './protocols';
 
-const getUsersAdapter = (): IGetUsersPort & getUsersAdapterReturnType => {
+const getUsersAdapter = (
+  userAdmin: AdminUserModel,
+  updateAccessToken: (newAccessToken: string) => void,
+  navigateToAuth: () => void,
+): IGetUsersPort & getUsersAdapterReturnType => {
   // url of api
   const url = apiUrls.core.getUsers;
   // make the options of request
@@ -14,7 +19,14 @@ const getUsersAdapter = (): IGetUsersPort & getUsersAdapterReturnType => {
     method: 'GET',
   };
   // make the httpHandler
-  const httpProvider = new HTTPPovider();
+  const httpProvider = new HTTPPovider(
+    {
+      accessToken: userAdmin.adminUserData.accessToken,
+      refreshToken: userAdmin.adminUserData.refreshToken,
+    },
+    updateAccessToken,
+    navigateToAuth,
+  );
 
   const httpHandler = async () => httpProvider.request<GetUsersResponse>(options);
 
diff --git a/src/driven/boundaries/http-boundary/httpBoundary.ts b/src/driven/boundaries/http-boundary/httpBoundary.ts
index 69ff31b..47a236c 100644
--- a/src/driven/boundaries/http-boundary/httpBoundary.ts
+++ b/src/driven/boundaries/http-boundary/httpBoundary.ts
@@ -1,22 +1,88 @@
-import axios from 'axios';
+/* eslint-disable consistent-return */
+/* eslint-disable no-param-reassign */
+import axios, { AxiosInstance } from 'axios';
 import { staticMessages } from '~/driven/utils/constants/staticMessages';
 import { ApiGlobalResponseObject } from '~/driven/utils/protocols/serviceProtocols';
+import { apiUrls } from '~/driven/utils/configs/appConfig';
 import { HttpOptionsType } from './protocols';
 
+interface IUserTokens {
+  accessToken: string | null;
+  refreshToken: string | null;
+}
 export class HTTPPovider {
+  private userTokens: IUserTokens;
+
+  private updateAccessToken: (newAccessToken: string) => void;
+
+  private navigateToAuth: () => void;
+
+  constructor(
+    userTokens: IUserTokens,
+    updateAccessToken: (newAccessToken: string) => void,
+    navigateToAuth: () => void,
+  ) {
+    this.userTokens = userTokens;
+    this.updateAccessToken = updateAccessToken;
+    this.navigateToAuth = navigateToAuth;
+  }
+
+  private initalizeAxiosInstance() {
+    const instance = axios.create();
+
+    return instance;
+  }
+
+  private handleRequestInterceptor() {
+    const axiosInstance = this.initalizeAxiosInstance();
+    axiosInstance.interceptors.request.use((config) => {
+      config.headers.Authorization = `Bearer ${this.userTokens.accessToken}`;
+      return config;
+    });
+
+    return axiosInstance;
+  }
+
   async request<R>(customOptions: HttpOptionsType) {
-    const options: HttpOptionsType = {
-      ...customOptions,
-      headers: {
-        ...customOptions.headers,
-        mode: 'cors',
-        credentials: 'include',
-        Authorization: `Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4NXh0WnA5eThxVDBXVDkwUFpuUkRja3N4LWw0clVyM0tHQW5JSU9DckJNIn0.eyJleHAiOjE2ODQ4MzM5NzcsImlhdCI6MTY4NDc0NzU3NywianRpIjoiYjE5MDEyNGItYzRjNC00NzlkLThkYWItN2VjODc1MjljZWQyIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9kaXBhbF9kZXYiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiY2RmYzY3YzQtZGJkOC00NGVhLWI0OWEtYjQ3MjZhMzNmOTAxIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29tZm9ydGVjaCIsInNlc3Npb25fc3RhdGUiOiJiYjFmNjc3OC0xMzlhLTRmNzItOWM3Ny01NjAwMWU0NDYzNjQiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1tYXN0ZXIiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiY29tZm9ydGVjaCI6eyJyb2xlcyI6WyJ1c2VyIiwib3BlcmF0b3IiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImJiMWY2Nzc4LTEzOWEtNGY3Mi05Yzc3LTU2MDAxZTQ0NjM2NCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiKzc3Nzc3Nzc3Nzc3In0.qJS5_c9g2AADwusGpquWw7zMvc42tzJ0yUMcM6jI6F2MNH2tFDqMhvG0nEnCwXIxJA54DZL8HHPDoxkhq_xyP2SSRKEU-S7pncpa2acNzOYT68pLxBD6s3W-akQxxJVlr92RtegqaHf2BAZMwdMJl4VreX_avPCrEdPzv2dEMX7a2wxteYgzQJsYtaaVyCO4QADMiNVMWgXE00Hnn5Rxuhpe9Y7Kl9cWCO5JY63gYXGFC9yUBEqEYl6o9d6XKMkuiaLJRE2l4k5ycKuJWUjhvCaL7J_f68vJzNhkiuMqmX5q08SDlgktNHzyKTVXkndKz2EpQemzM6SXPLnohPwjAg`,
-      },
-    };
-    const response = await axios<ApiGlobalResponseObject<R>>(options);
+    const axiosInstance = this.handleRequestInterceptor();
+    this.responseIncepter(axiosInstance);
+
+    const response = await axiosInstance<ApiGlobalResponseObject<R>>(customOptions);
     if (!response) throw new Error(staticMessages.service.errors[500]);
 
     return response.data.data;
   }
+
+  /**
+   * @todo should be handled in business logic
+   */
+  private async refreshAccessToken() {
+    try {
+      const response = await axios.post(apiUrls.generic.authRefresh, {
+        refresh_token: this.userTokens.refreshToken,
+      });
+      this.updateAccessToken(response.data.access_token as string);
+      return response.data.access_token;
+    } catch (err) {
+      this.navigateToAuth();
+    }
+  }
+
+  private responseIncepter(axiosInstance: AxiosInstance) {
+    axiosInstance.interceptors.response.use(
+      (response) => response,
+      (error) => {
+        const originalRequest = error.config;
+
+        if (error.response.status === 401 && error.response.message === 'Unauthorized') {
+          const newAccessToken = this.refreshAccessToken().then(() => {
+            originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
+            return axios(originalRequest);
+          });
+        }
+
+        return Promise.reject(error);
+      },
+    );
+  }
 }
diff --git a/src/driven/utils/configs/appConfig.ts b/src/driven/utils/configs/appConfig.ts
index d6d78fa..2b4d4f8 100644
--- a/src/driven/utils/configs/appConfig.ts
+++ b/src/driven/utils/configs/appConfig.ts
@@ -36,5 +36,6 @@ export const apiUrls = {
   generic: {
     authPhonenumber: `${ENVs.apiAuthOrigin}${ENVs.apiAuthPhonenumber}`,
     authLogin: `${ENVs.apiAuthOrigin}${ENVs.apiAuthLogin}`,
+    authRefresh: `${ENVs.apiAuthOrigin}${ENVs.apiAuthRefresh}`,
   },
 };
diff --git a/src/driven/utils/constants/envs.ts b/src/driven/utils/constants/envs.ts
index e412194..e347844 100644
--- a/src/driven/utils/constants/envs.ts
+++ b/src/driven/utils/constants/envs.ts
@@ -3,6 +3,7 @@ export const ENVs = {
   apiAuthOrigin: process.env.VITE_API_AUTH_ORIGIN,
   apiAuthPhonenumber: process.env.VITE_API_AUTH_PHONENUMBER,
   apiAuthLogin: process.env.VITE_API_AUTH_LOGIN,
+  apiAuthRefresh: process.env.VITE_API_AUTH_REFRESH,
   apiGetPlaces: process.env.VITE_API_PLACES,
   apiGetUsers: process.env.VITE_API_USERS,
   apiCreateUserAccount: process.env.VITE_API_USERS_ACCOUNT,
diff --git a/src/driven/utils/helpers/contexts/userContext.tsx b/src/driven/utils/helpers/contexts/userContext.tsx
index ed3f92e..f53331d 100644
--- a/src/driven/utils/helpers/contexts/userContext.tsx
+++ b/src/driven/utils/helpers/contexts/userContext.tsx
@@ -2,7 +2,7 @@
 import React, { useState } from 'react';
 import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 
-interface IUserContext {
+export interface IUserContext {
   user: AdminUserModel | null;
   setUser: React.Dispatch<React.SetStateAction<AdminUserModel | null>> | null;
 }
diff --git a/src/driven/utils/helpers/globalHelpers.ts b/src/driven/utils/helpers/globalHelpers.ts
index 1fc5a84..92fb772 100644
--- a/src/driven/utils/helpers/globalHelpers.ts
+++ b/src/driven/utils/helpers/globalHelpers.ts
@@ -1,5 +1,9 @@
 import StateManagementService from '~/driven/boundaries/state-management';
+import StorageService from '~/driven/boundaries/storage-boundary';
+import { NavigateFunction } from 'react-router-dom';
+import { appConfig, routes } from '../configs/appConfig';
 import { errorHandlingStateTypes, UIErrorHandling } from './protocols/globalHelpersProtocols';
+import { IUserContext } from './contexts/userContext';
 
 export const UIErrorHandlingFactory = <DATA_RESPONSE>({
   state,
@@ -26,3 +30,21 @@ export const prepareStateManagementForVM = <ReturnType>(apiUrl: string, model: (
 export const checkPhoneNumberInput = (newValue: string) => {
   return (Number.isFinite(+newValue) || newValue === '+') && newValue.length <= 12;
 };
+
+export const updateAccessToken = (newAccessToken: string, userContext: IUserContext) => {
+  const { setUser, user } = userContext;
+  if (!user || !setUser) return;
+  const storage = StorageService.localStorage();
+  user.adminUserData.accessToken = newAccessToken;
+  storage.setData(appConfig.adminUserStorageKey, user);
+  setUser(user);
+};
+
+export const navigateToAuth = (userCtx: IUserContext, navigate: NavigateFunction) => {
+  const { setUser } = userCtx;
+  const storage = StorageService.localStorage();
+  storage.deleteData(appConfig.adminUserStorageKey);
+  if (!setUser) return;
+  setUser(null);
+  navigate(routes.authentication);
+};
diff --git a/src/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator.ts b/src/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator.ts
new file mode 100644
index 0000000..077d49a
--- /dev/null
+++ b/src/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator.ts
@@ -0,0 +1,24 @@
+import { useNavigate } from 'react-router-dom';
+import { useUser } from '../contexts/userContext';
+import { navigateToAuth, updateAccessToken } from '../globalHelpers';
+
+const useGetNavigatorAndTokenUpdater = () => {
+  const userData = useUser();
+  const navigate = useNavigate();
+
+  const notLoginAuth = () => {
+    navigateToAuth(userData, navigate);
+  };
+
+  const accessTokenUpdateHandler = (newAccessToken: string) => {
+    updateAccessToken(newAccessToken, userData);
+  };
+  return {
+    notLoginAuth,
+    accessTokenUpdateHandler,
+    userData,
+    navigate,
+  };
+};
+
+export default useGetNavigatorAndTokenUpdater;
diff --git a/src/driving/application/core/common/table-row/view/TableRow.tsx b/src/driving/application/core/common/table-row/view/TableRow.tsx
index 714d674..5156de4 100644
--- a/src/driving/application/core/common/table-row/view/TableRow.tsx
+++ b/src/driving/application/core/common/table-row/view/TableRow.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable react/no-array-index-key */
 import React from 'react';
 import RowItem from './table-row-item/view/RowItem';
 import { ITableRowProps } from './protocols';
@@ -6,7 +7,14 @@ export default function TableRowView(props: ITableRowProps) {
   const { isSelected, setSelectedRowId, rowData } = props;
   const { rowId, rowItemsTitle } = rowData;
   const columns = rowItemsTitle.map((rowItemTitle, index) => {
-    return <RowItem key={rowItemTitle} hasCheckbox={index === 0} isSelected={isSelected} title={rowItemTitle} />;
+    return (
+      <RowItem
+        key={(rowItemTitle || 'row') + index}
+        hasCheckbox={index === 0}
+        isSelected={isSelected}
+        title={rowItemTitle}
+      />
+    );
   });
 
   return <tr onClick={() => setSelectedRowId(rowId)}>{columns}</tr>;
diff --git a/src/driving/application/core/create-user/infra/CreateUser.tsx b/src/driving/application/core/create-user/infra/CreateUser.tsx
index 1b626f7..b68b686 100644
--- a/src/driving/application/core/create-user/infra/CreateUser.tsx
+++ b/src/driving/application/core/create-user/infra/CreateUser.tsx
@@ -2,14 +2,27 @@ import React from 'react';
 import createAccountAdapter from '~/driven/adapters/create-account-adapter/createAccountAdapter';
 import createProfileAdapter from '~/driven/adapters/create-profile-adapter/createProfileAdapter';
 import CreateUserInfra from '~/business-logic/core/users/create-user';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
+import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
 import CreateUserView from '../view/CreateUserView';
 import useCreateUserVM from '../viewmodel/CreateUserVM';
 import createUserModel from '../model/createUserModel';
 
 export default function CreateUser() {
+  const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
+
+  const { user } = userData;
   // get adapters from driven layer
-  const createAccountDrivenAdapter = createAccountAdapter();
-  const createProfileDrivenAdapter = createProfileAdapter();
+  const createAccountDrivenAdapter = createAccountAdapter(
+    user as AdminUserModel,
+    accessTokenUpdateHandler,
+    notLoginAuth,
+  );
+  const createProfileDrivenAdapter = createProfileAdapter(
+    user as AdminUserModel,
+    accessTokenUpdateHandler,
+    notLoginAuth,
+  );
   // pass to the logic and get the usecase
   const createUserInfra = new CreateUserInfra(createAccountDrivenAdapter, createProfileDrivenAdapter);
   const createUserLogic = createUserInfra.execute();
diff --git a/src/driving/application/core/places-list/infra/PlacesList.tsx b/src/driving/application/core/places-list/infra/PlacesList.tsx
index 0b41617..3b46a98 100644
--- a/src/driving/application/core/places-list/infra/PlacesList.tsx
+++ b/src/driving/application/core/places-list/infra/PlacesList.tsx
@@ -3,12 +3,17 @@ import getPlaces from '~/business-logic/core/places/get-places';
 import getPlacesAdapter from '~/driven/adapters/get-places-adapter/getPlacesAdapter';
 import PlacesModel from '~/business-logic/core/places/common/model/placesModel';
 import { prepareStateManagementForVM } from '~/driven/utils/helpers/globalHelpers';
+import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import PlacesListView from '../view/PlacesListView';
 import usePlacesListVM from '../viewmodel/placesListVM';
 import placesListModel from '../model/placesListModel';
 
 const prepareTheLogicForModel = () => {
-  const gettingPlacesDrivenAdapter = getPlacesAdapter();
+  const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
+
+  const { user } = userData;
+  const gettingPlacesDrivenAdapter = getPlacesAdapter(user as AdminUserModel, accessTokenUpdateHandler, notLoginAuth);
   const { url } = gettingPlacesDrivenAdapter;
   const getingPlacesLogic = getPlaces(gettingPlacesDrivenAdapter);
   return { getingPlacesLogic, url };
diff --git a/src/driving/application/core/users-list/infra/UsersList.tsx b/src/driving/application/core/users-list/infra/UsersList.tsx
index 6a6894a..669731f 100644
--- a/src/driving/application/core/users-list/infra/UsersList.tsx
+++ b/src/driving/application/core/users-list/infra/UsersList.tsx
@@ -3,19 +3,24 @@ import getUsersAdapter from '~/driven/adapters/get-users-adapter/getUsersAdapter
 import getUsers from '~/business-logic/core/users/get-users';
 import UsersModel from '~/business-logic/core/users/common/data/model/usersModel';
 import { prepareStateManagementForVM } from '~/driven/utils/helpers/globalHelpers';
+import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
+import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
 import useUsersListVM from '../viewmodel/usersListVM';
 import UsersListView from '../view/UsersListView';
 import usersListModel from '../model/usersListModel';
 
-const prepareTheLogicForModel = () => {
-  const gettingUsersDrivenAdapter = getUsersAdapter();
+const usePrepareTheLogicForModel = () => {
+  const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
+
+  const { user } = userData;
+  const gettingUsersDrivenAdapter = getUsersAdapter(user as AdminUserModel, accessTokenUpdateHandler, notLoginAuth);
   const { url } = gettingUsersDrivenAdapter;
   const getingusersLogic = getUsers(gettingUsersDrivenAdapter);
   return { getingusersLogic, url };
 };
 
 export default function UsersList() {
-  const { getingusersLogic, url } = prepareTheLogicForModel();
+  const { getingusersLogic, url } = usePrepareTheLogicForModel();
   const usersModel = async () => await usersListModel(getingusersLogic);
   const useGetusersList = prepareStateManagementForVM<UsersModel>(url, usersModel);
   const { selectedRowId, setSelectedRowId, usersData } = useUsersListVM({
diff --git a/src/driving/application/generic/authentication/infra/Authentication.tsx b/src/driving/application/generic/authentication/infra/Authentication.tsx
index a2f5608..76ff8aa 100644
--- a/src/driving/application/generic/authentication/infra/Authentication.tsx
+++ b/src/driving/application/generic/authentication/infra/Authentication.tsx
@@ -3,13 +3,17 @@ import authAdminPhoneNumberDriven from '~/driven/adapters/auth-admin-phonenumber
 import phonenumberAuthInfra from '~/business-logic/generic/admin-user/authentication/phonnumber-auth';
 import authAdminLogin from '~/driven/adapters/auth-admin-login/authAdminLogin';
 import otpAuthInfra from '~/business-logic/generic/admin-user/authentication/otp-auth';
+import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
 import AuthenticationView from '../view/AuthenticationView';
 
 export default function Authentication() {
-  const authPhonenumberDriven = authAdminPhoneNumberDriven();
+  const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
+  const { user } = userData;
+
+  const authPhonenumberDriven = authAdminPhoneNumberDriven(user, accessTokenUpdateHandler, notLoginAuth);
   const authPhoneLogic = phonenumberAuthInfra(authPhonenumberDriven);
 
-  const authLoginDriven = authAdminLogin();
+  const authLoginDriven = authAdminLogin(user, accessTokenUpdateHandler, notLoginAuth);
   const otpAuthLogic = otpAuthInfra(authLoginDriven.httpHandler);
 
   return <AuthenticationView authPhone={authPhoneLogic} otpAuth={otpAuthLogic} />;
diff --git a/src/driving/main/pages/layouts/MainPageLayout.tsx b/src/driving/main/pages/layouts/MainPageLayout.tsx
index 86da94c..bc004c9 100644
--- a/src/driving/main/pages/layouts/MainPageLayout.tsx
+++ b/src/driving/main/pages/layouts/MainPageLayout.tsx
@@ -11,7 +11,7 @@ import Sidebar from '~/driving/application/support/sidebar';
  */
 export default function MainPageLayout() {
   const { user, setUser } = useUser();
-
+  console.log('hi');
   useEffect(() => {
     const storage = StorageService.localStorage<AdminUserModel>();
     const currentUser = storage.getData(appConfig.adminUserStorageKey);
diff --git a/src/driving/main/pages/layouts/UserLoginLayout.tsx b/src/driving/main/pages/layouts/UserLoginLayout.tsx
index b83e787..33683f2 100644
--- a/src/driving/main/pages/layouts/UserLoginLayout.tsx
+++ b/src/driving/main/pages/layouts/UserLoginLayout.tsx
@@ -5,7 +5,7 @@ import { useUser } from '~/driven/utils/helpers/contexts/userContext';
 
 export default function UserLoginLayout() {
   const { user } = useUser();
-
-  if (user) return <Navigate to={routes.usersList} replace />;
+  console.log('hhhh');
+  if (user && user.adminUserData.accessToken) return <Navigate to={routes.usersList} replace />;
   return <Outlet />;
 }