This is an automated email from the ASF dual-hosted git repository.

LauraXia123 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 64009ee93c [MINOR] fix(web-v2): Normalize service admins configuration 
(#12046)
64009ee93c is described below

commit 64009ee93c770d0b99cea5053ce5840924afff8d
Author: gaohong <[email protected]>
AuthorDate: Fri Jul 17 13:57:48 2026 +0800

    [MINOR] fix(web-v2): Normalize service admins configuration (#12046)
    
    ### What changes were proposed in this pull request?
    
    This PR adds a shared `normalizeServiceAdmins` utility and uses it in
    the Metalake list page and user settings component.
    
    The utility normalizes `serviceAdmins` into an array and supports both
    formats returned by the configuration API:
    
    - An array of user names
    - A comma-separated string of user names
    
    Unsupported values are normalized to an empty array.
    
    ### Why are the changes needed?
    
    `serviceAdmins` can be returned as either an array or a comma-separated
    string. The previous duplicated page-level logic could call
    `.split(',')` on a non-string value, causing a frontend runtime error.
    
    This change centralizes the normalization logic and prevents the UI from
    failing when the configuration value has an unexpected type.
    
    Fix: N/A
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. The UI now handles both supported `serviceAdmins` formats
    consistently and no longer fails for unsupported values.
    
    No user-facing API or configuration property is added or changed.
    
    ### How was this patch tested?
    
    - Ran `git diff --check upstream/main...HEAD`.
    - Verified that both existing `serviceAdmins` consumers use the shared
    utility:
      - `web-v2/web/src/app/rootLayout/UserSetting.js`
      - `web-v2/web/src/app/metalakes/page.js`
    
    No automated frontend tests were run.
    
    Co-authored-by: gaohong <[email protected]>
---
 web-v2/web/src/app/metalakes/page.js         |  3 ++-
 web-v2/web/src/app/rootLayout/UserSetting.js |  3 ++-
 web-v2/web/src/lib/utils/serviceAdmins.js    | 30 ++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/web-v2/web/src/app/metalakes/page.js 
b/web-v2/web/src/app/metalakes/page.js
index 183b04a329..1f9c468846 100644
--- a/web-v2/web/src/app/metalakes/page.js
+++ b/web-v2/web/src/app/metalakes/page.js
@@ -37,6 +37,7 @@ import {
 } from '@/lib/store/metalakes'
 import { to } from '@/lib/utils'
 import { formatToDateTime } from '@/lib/utils/date'
+import { normalizeServiceAdmins } from '@/lib/utils/serviceAdmins'
 import Icons from '@/components/Icons'
 import GetOwner from '@/components/GetOwner'
 import PropertiesContent from '@/components/PropertiesContent'
@@ -70,7 +71,7 @@ const MetalakeList = () => {
   const [ownerRefreshKey, setOwnerRefreshKey] = useState(0)
   const auth = useAppSelector(state => state.auth)
   const { serviceAdmins, authUser, anthEnable } = auth
-  const admins = Array.isArray(serviceAdmins) ? serviceAdmins : (serviceAdmins 
|| '').split(',')
+  const admins = normalizeServiceAdmins(serviceAdmins)
   const isServiceAdmin = admins.includes(authUser?.name)
   const dispatch = useAppDispatch()
   const store = useAppSelector(state => state.metalakes)
diff --git a/web-v2/web/src/app/rootLayout/UserSetting.js 
b/web-v2/web/src/app/rootLayout/UserSetting.js
index d3041ae2a8..a4a8fc251e 100644
--- a/web-v2/web/src/app/rootLayout/UserSetting.js
+++ b/web-v2/web/src/app/rootLayout/UserSetting.js
@@ -24,6 +24,7 @@ import { LogoutOutlined, PlusOutlined, UserOutlined } from 
'@ant-design/icons'
 import { Avatar, Dropdown, Tooltip } from 'antd'
 import { usePathname, useSearchParams, useRouter } from 'next/navigation'
 import { cn } from '@/lib/utils/tailwind'
+import { normalizeServiceAdmins } from '@/lib/utils/serviceAdmins'
 import { useAppSelector, useAppDispatch } from '@/lib/hooks/useStore'
 import Loading from '@/components/Loading'
 import { fetchMetalakes, resetMetalakeStore } from '@/lib/store/metalakes'
@@ -41,7 +42,7 @@ export default function UserSetting() {
   const [showLogoutButton, setShowLogoutButton] = useState(false)
   const auth = useAppSelector(state => state.auth)
   const { serviceAdmins, authUser, anthEnable } = auth
-  const admins = Array.isArray(serviceAdmins) ? serviceAdmins : (serviceAdmins 
|| '').split(',')
+  const admins = normalizeServiceAdmins(serviceAdmins)
   const isServiceAdmin = admins.includes(authUser?.name)
   const [session, setSession] = useState({})
   const router = useRouter()
diff --git a/web-v2/web/src/lib/utils/serviceAdmins.js 
b/web-v2/web/src/lib/utils/serviceAdmins.js
new file mode 100644
index 0000000000..43717f9471
--- /dev/null
+++ b/web-v2/web/src/lib/utils/serviceAdmins.js
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+export const normalizeServiceAdmins = serviceAdmins => {
+  if (Array.isArray(serviceAdmins)) {
+    return serviceAdmins
+  }
+
+  if (typeof serviceAdmins === 'string') {
+    return serviceAdmins.split(',')
+  }
+
+  return []
+}

Reply via email to