From 7bfc00f10ea1318753d8fe555c0aaf3dd4a80972 Mon Sep 17 00:00:00 2001
From: darth-coder00 <86726556+darth-coder00@users.noreply.github.com>
Date: Tue, 26 Apr 2022 02:48:02 +0530
Subject: [PATCH] Fixed user profile sync, test connection and toast
progressbar issues (#4480)
---
.../src/main/resources/ui/src/App.tsx | 3 +-
.../auth-provider/AuthProvider.tsx | 79 ++++++++-----------
.../ServiceConfig/ConnectionConfigForm.tsx | 4 +-
.../resources/ui/src/constants/constants.ts | 1 -
.../ui/src/constants/toast.constants.ts | 19 +++++
.../src/main/resources/ui/src/jsons/en.ts | 1 +
.../resources/ui/src/pages/signup/index.tsx | 2 +-
.../{UsedDataUtils.ts => UserDataUtils.ts} | 38 ++++++++-
8 files changed, 95 insertions(+), 52 deletions(-)
create mode 100644 openmetadata-ui/src/main/resources/ui/src/constants/toast.constants.ts
rename openmetadata-ui/src/main/resources/ui/src/utils/{UsedDataUtils.ts => UserDataUtils.ts} (66%)
diff --git a/openmetadata-ui/src/main/resources/ui/src/App.tsx b/openmetadata-ui/src/main/resources/ui/src/App.tsx
index 2f74136d153..a0cfc079ac8 100644
--- a/openmetadata-ui/src/main/resources/ui/src/App.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/App.tsx
@@ -27,6 +27,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';
import { AuthProvider } from './authentication/auth-provider/AuthProvider';
+import { toastOptions } from './constants/toast.constants';
import AppRouter from './router/AppRouter';
const App: FunctionComponent = () => {
@@ -49,7 +50,7 @@ const App: FunctionComponent = () => {
-
+
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/authentication/auth-provider/AuthProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/authentication/auth-provider/AuthProvider.tsx
index cf6ed4d8eb0..b39c10caeb5 100644
--- a/openmetadata-ui/src/main/resources/ui/src/authentication/auth-provider/AuthProvider.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/authentication/auth-provider/AuthProvider.tsx
@@ -16,7 +16,6 @@ import { Configuration } from '@azure/msal-browser';
import { MsalProvider } from '@azure/msal-react';
import { LoginCallback } from '@okta/okta-react';
import { AxiosError, AxiosResponse } from 'axios';
-import { CookieStorage } from 'cookie-storage';
import jwtDecode, { JwtPayload } from 'jwt-decode';
import { isEmpty, isNil } from 'lodash';
import { observer } from 'mobx-react';
@@ -44,11 +43,7 @@ import {
} from '../../axiosAPIs/userAPI';
import Loader from '../../components/Loader/Loader';
import { NO_AUTH } from '../../constants/auth.constants';
-import {
- isAdminUpdated,
- oidcTokenKey,
- ROUTES,
-} from '../../constants/constants';
+import { oidcTokenKey, ROUTES } from '../../constants/constants';
import { ClientErrors } from '../../enums/axios.enum';
import { AuthTypes } from '../../enums/signin.enum';
import { User } from '../../generated/entity/teams/user';
@@ -62,9 +57,12 @@ import {
msalInstance,
setMsalInstance,
} from '../../utils/AuthProvider.util';
-import { getImages } from '../../utils/CommonUtils';
import { showErrorToast } from '../../utils/ToastUtils';
-import { fetchAllUsers } from '../../utils/UsedDataUtils';
+import {
+ fetchAllUsers,
+ getUserDataFromOidc,
+ matchUserDetails,
+} from '../../utils/UserDataUtils';
import Auth0Authenticator from '../authenticators/Auth0Authenticator';
import MsalAuthenticator from '../authenticators/MsalAuthenticator';
import OidcAuthenticator from '../authenticators/OidcAuthenticator';
@@ -78,7 +76,6 @@ interface AuthProviderProps {
children: ReactNode;
}
-const cookieStorage = new CookieStorage();
const userAPIQueryFields = 'profile,teams,roles';
export const AuthProvider = ({
@@ -165,45 +162,33 @@ export const AuthProvider = ({
}
})
.catch((err: AxiosError) => {
- if (err.response?.data.code === 404) {
- resetUserDetails();
+ resetUserDetails();
+ if (err.response?.data.code !== 404) {
+ showErrorToast(
+ err,
+ jsonData['api-error-messages']['fetch-logged-in-user-error']
+ );
}
});
};
- const getUpdatedUser = (data: User, user: OidcUser) => {
- let getAdminCookie = localStorage.getItem(isAdminUpdated);
-
- // TODO: Remove when using cookie no more
- if (!getAdminCookie) {
- getAdminCookie = cookieStorage.getItem(isAdminUpdated);
- if (getAdminCookie) {
- localStorage.setItem(isAdminUpdated, getAdminCookie);
- }
- }
-
- if (getAdminCookie) {
- appState.updateUserDetails(data);
- } else {
- const updatedData = {
- isAdmin: data.isAdmin,
- email: data.email,
- name: data.name,
- displayName: user.profile.name,
- profile: { images: getImages(user.profile.picture ?? '') },
- };
- updateUser(updatedData)
- .then((res: AxiosResponse) => {
+ const getUpdatedUser = (updatedData: User, existingData: User) => {
+ const { isAdmin, name, displayName, profile, email } = updatedData;
+ updateUser({ isAdmin, name, displayName, profile, email })
+ .then((res: AxiosResponse) => {
+ if (res.data) {
appState.updateUserDetails(res.data);
- localStorage.setItem(isAdminUpdated, 'true');
- })
- .catch((error: AxiosError) => {
- showErrorToast(
- error,
- jsonData['api-error-messages']['update-admin-profile-error']
- );
- });
- }
+ } else {
+ throw jsonData['api-error-messages']['unexpected-server-response'];
+ }
+ })
+ .catch((error: AxiosError) => {
+ appState.updateUserDetails(existingData);
+ showErrorToast(
+ error,
+ jsonData['api-error-messages']['update-admin-profile-error']
+ );
+ });
};
const handleSuccessfulLogin = (user: OidcUser) => {
@@ -211,11 +196,13 @@ export const AuthProvider = ({
getUserByName(getNameFromEmail(user.profile.email), userAPIQueryFields)
.then((res: AxiosResponse) => {
if (res.data) {
- if (res.data?.isAdmin) {
- getUpdatedUser(res.data, user);
+ const updatedUserData = getUserDataFromOidc(res.data, user);
+ if (!matchUserDetails(res.data, updatedUserData, ['profile'])) {
+ getUpdatedUser(updatedUserData, res.data);
+ } else {
+ appState.updateUserDetails(res.data);
}
getUserPermissions();
- appState.updateUserDetails(res.data);
fetchAllUsers();
handledVerifiedUser();
}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ServiceConfig/ConnectionConfigForm.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ServiceConfig/ConnectionConfigForm.tsx
index 857cb267be7..159b96eaf85 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ServiceConfig/ConnectionConfigForm.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ServiceConfig/ConnectionConfigForm.tsx
@@ -89,8 +89,10 @@ const ConnectionConfigForm: FunctionComponent = ({
};
const handleTestConnection = (formData: ConfigData) => {
+ const updatedFormData = escapeBackwardSlashChar(formData);
+
return new Promise((resolve, reject) => {
- TestConnection(formData, 'Database')
+ TestConnection(updatedFormData, 'Database')
.then((res) => {
// This api only responds with status 200 on success
// No data sent on api success
diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts
index c3180f24344..c2e4dd4c636 100644
--- a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts
@@ -25,7 +25,6 @@ export const SIDEBAR_WIDTH_EXPANDED = 290;
export const LOCALSTORAGE_RECENTLY_VIEWED = `recentlyViewedData_${COOKIE_VERSION}`;
export const LOCALSTORAGE_RECENTLY_SEARCHED = `recentlySearchedData_${COOKIE_VERSION}`;
export const oidcTokenKey = 'oidcIdToken';
-export const isAdminUpdated = 'isAdminUpdated';
export const TERM_ADMIN = 'Admin';
export const TERM_USER = 'User';
export const imageTypes = {
diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/toast.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/toast.constants.ts
new file mode 100644
index 00000000000..8568a42a2f8
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/constants/toast.constants.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ToastOptions } from 'react-toastify';
+
+export const toastOptions: ToastOptions = {
+ autoClose: false,
+ hideProgressBar: true,
+};
diff --git a/openmetadata-ui/src/main/resources/ui/src/jsons/en.ts b/openmetadata-ui/src/main/resources/ui/src/jsons/en.ts
index 29d45b82930..63769092912 100644
--- a/openmetadata-ui/src/main/resources/ui/src/jsons/en.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/jsons/en.ts
@@ -82,6 +82,7 @@ const jsonData = {
'fetch-ingestion-error': 'Error while fetching ingestion workflow!',
'fetch-lineage-error': 'Error while fetching lineage data!',
'fetch-lineage-node-error': 'Error while fetching lineage node!',
+ 'fetch-logged-in-user-error': 'Error while fetching logged-in user!',
'fetch-pipeline-details-error': 'Error while fetching pipeline details!',
'fetch-pipeline-status-error': 'Error while fetching pipeline status!',
'fetch-policy-error': 'Error while fetching policy details!',
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx
index 2f48b98b098..4a47d11ff18 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx
@@ -30,7 +30,7 @@ import { getNameFromEmail } from '../../utils/AuthProvider.util';
import { getImages } from '../../utils/CommonUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
import { showErrorToast } from '../../utils/ToastUtils';
-import { fetchAllUsers } from '../../utils/UsedDataUtils';
+import { fetchAllUsers } from '../../utils/UserDataUtils';
const Signup = () => {
const [selectedTeams, setSelectedTeams] = useState>(
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/UsedDataUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/UserDataUtils.ts
similarity index 66%
rename from openmetadata-ui/src/main/resources/ui/src/utils/UsedDataUtils.ts
rename to openmetadata-ui/src/main/resources/ui/src/utils/UserDataUtils.ts
index d035efe8cba..d184edac67d 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/UsedDataUtils.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/UserDataUtils.ts
@@ -12,11 +12,15 @@
*/
import { AxiosResponse } from 'axios';
+import { isEmpty, isEqual } from 'lodash';
import AppState from '../AppState';
+import { OidcUser } from '../authentication/auth-provider/AuthProvider.interface';
import { getRoles } from '../axiosAPIs/rolesAPI';
import { getTeams } from '../axiosAPIs/teamsAPI';
import { getUsers } from '../axiosAPIs/userAPI';
import { API_RES_MAX_SIZE } from '../constants/constants';
+import { User } from '../generated/entity/teams/user';
+import { getImages } from './CommonUtils';
// Moving this code here from App.tsx
const getAllUsersList = (arrQueryFields = ''): void => {
@@ -53,6 +57,36 @@ export const fetchAllUsers = () => {
getAllUsersList('profile,teams,roles');
getAllTeams();
getAllRoles();
- // TODO: uncomment below line to update users list in real time.
- // setInterval(getAllUsersList, TIMEOUT.USER_LIST);
+};
+
+export const getUserDataFromOidc = (
+ userData: User,
+ oidcUser: OidcUser
+): User => {
+ const images = oidcUser.profile.picture
+ ? getImages(oidcUser.profile.picture)
+ : undefined;
+
+ return {
+ ...userData,
+ displayName: oidcUser.profile.name,
+ profile: !isEmpty(images) ? { images } : userData.profile,
+ };
+};
+
+export const matchUserDetails = (
+ userData: User,
+ newUser: User,
+ mapFields: Array
+) => {
+ let isMatch = true;
+ for (const field of mapFields) {
+ if (!isEqual(userData[field], newUser[field])) {
+ isMatch = false;
+
+ break;
+ }
+ }
+
+ return isMatch;
};