From 3a3de44903fa20638d705333489c233b99b6ef95 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <p.gawron@atcomp.pl>
Date: Thu, 16 May 2024 13:19:36 +0200
Subject: [PATCH] user privileges are fetched together with other user data

---
 .../LoginModal/LoginModal.component.test.tsx    | 13 ++++++-------
 src/models/userPrivilegesSchema.ts              |  4 ++--
 src/models/userSchema.ts                        |  4 ++--
 src/redux/user/user.reducers.test.ts            |  7 +++----
 src/redux/user/user.thunks.ts                   | 17 +++++------------
 src/types/models.ts                             |  3 ++-
 src/utils/error-report/errorReporting.test.ts   |  7 ++-----
 7 files changed, 22 insertions(+), 33 deletions(-)

diff --git a/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx b/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
index ca8aef6c..5f95c9ac 100644
--- a/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
@@ -12,6 +12,7 @@ import { loginFixture } from '@/models/fixtures/loginFixture';
 import { overlaysFixture } from '@/models/fixtures/overlaysFixture';
 import { userPrivilegesFixture } from '@/models/fixtures/userPrivilegesFixture';
 import { MODAL_INITIAL_STATE_MOCK } from '@/redux/modal/modal.mock';
+import { userFixture } from '@/models/fixtures/userFixture';
 import { LoginModal } from './LoginModal.component';
 
 const mockedAxiosClient = mockNetworkResponse();
@@ -71,9 +72,7 @@ describe('LoginModal - component', () => {
   });
   it('should fetch user overlays when login is successful', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     mockedAxiosClient
       .onGet(
         apiPath.getAllUserOverlaysByCreatorQuery({
@@ -103,8 +102,8 @@ describe('LoginModal - component', () => {
   });
   it('should display loggedInMenuModal after successful login as admin', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient.onGet(apiPath.userPrivileges(loginFixture.login)).reply(HttpStatusCode.Ok, {
-      ...userPrivilegesFixture,
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, {
+      ...userFixture,
       privileges: [
         {
           privilegeType: 'IS_ADMIN',
@@ -142,8 +141,8 @@ describe('LoginModal - component', () => {
   });
   it('should display loggedInMenuModal after successful login as curator', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient.onGet(apiPath.userPrivileges(loginFixture.login)).reply(HttpStatusCode.Ok, {
-      ...userPrivilegesFixture,
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, {
+      ...userFixture,
       privileges: [
         {
           privilegeType: 'IS_CURATOR',
diff --git a/src/models/userPrivilegesSchema.ts b/src/models/userPrivilegesSchema.ts
index 28115b1a..f6beb466 100644
--- a/src/models/userPrivilegesSchema.ts
+++ b/src/models/userPrivilegesSchema.ts
@@ -1,10 +1,10 @@
 import { z } from 'zod';
 
-const userPrivilege = z.object({
+export const userPrivilegeSchema = z.object({
   privilegeType: z.string(),
   objectId: z.string().nullable(),
 });
 
 export const userPrivilegesSchema = z.object({
-  privileges: z.array(userPrivilege),
+  privileges: z.array(userPrivilegeSchema),
 });
diff --git a/src/models/userSchema.ts b/src/models/userSchema.ts
index 47f43c2c..aaf1ffd8 100644
--- a/src/models/userSchema.ts
+++ b/src/models/userSchema.ts
@@ -1,5 +1,5 @@
 import { z } from 'zod';
-import { userPrivilegesSchema } from '@/models/userPrivilegesSchema';
+import { userPrivilegeSchema } from '@/models/userPrivilegesSchema';
 import { ZERO } from '@/constants/common';
 
 export const userSchema = z.object({
@@ -14,7 +14,7 @@ export const userSchema = z.object({
   simpleColor: z.string().nullable(),
   removed: z.boolean(),
   termsOfUseConsent: z.boolean(),
-  privileges: z.array(userPrivilegesSchema),
+  privileges: z.array(userPrivilegeSchema),
   active: z.boolean(),
   confirmed: z.boolean(),
   ldapAccountAvailable: z.boolean(),
diff --git a/src/redux/user/user.reducers.test.ts b/src/redux/user/user.reducers.test.ts
index 24007e90..43cb814f 100644
--- a/src/redux/user/user.reducers.test.ts
+++ b/src/redux/user/user.reducers.test.ts
@@ -42,9 +42,7 @@ describe('user reducer', () => {
 
   it('should update store after successful login query', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     await store.dispatch(login(CREDENTIALS));
     const { authenticated, loading } = store.getState().user;
 
@@ -54,6 +52,7 @@ describe('user reducer', () => {
 
   it('should update store on loading login query', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     const loginPromise = store.dispatch(login(CREDENTIALS));
 
     const { authenticated, loading } = store.getState().user;
@@ -65,8 +64,8 @@ describe('user reducer', () => {
     const { authenticated: authenticatedFulfilled, loading: promiseFulfilled } =
       store.getState().user;
 
-    expect(authenticatedFulfilled).toBe(true);
     expect(promiseFulfilled).toEqual('succeeded');
+    expect(authenticatedFulfilled).toBe(true);
   });
 
   it('should update store after successful getSessionValid query', async () => {
diff --git a/src/redux/user/user.thunks.ts b/src/redux/user/user.thunks.ts
index 740cabd7..43aecbc9 100644
--- a/src/redux/user/user.thunks.ts
+++ b/src/redux/user/user.thunks.ts
@@ -3,22 +3,14 @@ import { createAsyncThunk } from '@reduxjs/toolkit';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { loginSchema } from '@/models/loginSchema';
 import { sessionSchemaValid } from '@/models/sessionValidSchema';
-import { Login, SessionValid, User, UserPrivileges } from '@/types/models';
+import { Login, SessionValid, User, UserPrivilege } from '@/types/models';
 import { USER_ROLE } from '@/constants/user';
 import { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import { closeModal, openLoggedInMenuModal } from '../modal/modal.slice';
 import { hasPrivilege } from './user.utils';
 
-const getUserRole = async (login: string): Promise<string> => {
-  const response = await axiosInstance.get<UserPrivileges>(apiPath.userPrivileges(login), {
-    withCredentials: true,
-  });
-
-  const {
-    data: { privileges },
-  } = response;
-
+const getUserRole = (privileges: UserPrivilege[]): string => {
   if (hasPrivilege(privileges, 'IS_ADMIN')) {
     return USER_ROLE.ADMIN;
   }
@@ -50,7 +42,8 @@ export const login = createAsyncThunk(
       const loginName = response.data.login;
 
       if (isDataValid) {
-        const role = await getUserRole(loginName);
+        const userData = await getUserData(loginName);
+        const role = getUserRole(userData.privileges);
 
         if (role !== USER_ROLE.ADMIN && role !== USER_ROLE.CURATOR) {
           dispatch(closeModal());
@@ -82,8 +75,8 @@ export const getSessionValid = createAsyncThunk('user/getSessionValid', async ()
     data: { login: loginName },
   } = response;
 
-  const role = await getUserRole(loginName);
   const userData = await getUserData(loginName);
+  const role = getUserRole(userData.privileges);
 
   if (isDataValid) {
     return {
diff --git a/src/types/models.ts b/src/types/models.ts
index 102ec508..ff160b0d 100644
--- a/src/types/models.ts
+++ b/src/types/models.ts
@@ -59,7 +59,7 @@ import { submapConnection } from '@/models/submapConnection';
 import { targetElementSchema } from '@/models/targetElementSchema';
 import { targetSchema } from '@/models/targetSchema';
 import { targetSearchNameResult } from '@/models/targetSearchNameResult';
-import { userPrivilegesSchema } from '@/models/userPrivilegesSchema';
+import { userPrivilegeSchema, userPrivilegesSchema } from '@/models/userPrivilegesSchema';
 import { z } from 'zod';
 import { userSchema } from '@/models/userSchema';
 
@@ -113,6 +113,7 @@ export type TargetSearchNameResult = z.infer<typeof targetSearchNameResult>;
 export type TargetElement = z.infer<typeof targetElementSchema>;
 export type SubmapConnection = z.infer<typeof submapConnection>;
 export type UserPrivileges = z.infer<typeof userPrivilegesSchema>;
+export type UserPrivilege = z.infer<typeof userPrivilegeSchema>;
 export type User = z.infer<typeof userSchema>;
 export type MarkerType = z.infer<typeof markerTypeSchema>;
 export type MarkerPin = z.infer<typeof markerPinSchema>;
diff --git a/src/utils/error-report/errorReporting.test.ts b/src/utils/error-report/errorReporting.test.ts
index 3215452d..afc07563 100644
--- a/src/utils/error-report/errorReporting.test.ts
+++ b/src/utils/error-report/errorReporting.test.ts
@@ -1,14 +1,13 @@
-/* eslint-disable no-magic-numbers */
 import { createErrorData } from '@/utils/error-report/errorReporting';
 import { apiPath } from '@/redux/apiPath';
 import { HttpStatusCode } from 'axios';
 import { loginFixture } from '@/models/fixtures/loginFixture';
-import { userPrivilegesFixture } from '@/models/fixtures/userPrivilegesFixture';
 import { login } from '@/redux/user/user.thunks';
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { store } from '@/redux/store';
 import { getConfiguration } from '@/redux/configuration/configuration.thunks';
 import { configurationFixture } from '@/models/fixtures/configurationFixture';
+import { userFixture } from '@/models/fixtures/userFixture';
 
 const mockedAxiosClient = mockNetworkResponse();
 
@@ -40,9 +39,7 @@ describe('createErrorData', () => {
 
   it('should add login when logged', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     await store.dispatch(login(CREDENTIALS));
 
     const error = createErrorData(new Error('hello'));
-- 
GitLab