fix: show error message when web app access denied

This commit is contained in:
NFish 2025-04-16 09:09:21 +08:00
parent 480e9ebb82
commit c91398883c
4 changed files with 47 additions and 9 deletions

View File

@ -11,6 +11,7 @@ import { setAccessToken } from '@/app/components/share/utils'
import Button from '@/app/components/base/button'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { SSOProtocol } from '@/types/feature'
import Loading from '@/app/components/base/loading'
const WebSSOForm: FC = () => {
const { t } = useTranslation()
@ -91,6 +92,9 @@ const WebSSOForm: FC = () => {
init()
}, [message, processTokenAndRedirect, tokenFromUrl])
if (tokenFromUrl)
return <div className='flex items-center justify-center h-full'><Loading /></div>
if (systemFeatures.webapp_auth.enabled) {
if (systemFeatures.webapp_auth.allow_sso) {
return (

View File

@ -177,7 +177,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
})
}
setShowConfirmDelete(false)
}, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, t])
}, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, setAppDetail, t])
const handleClickAccessControl = useCallback(() => {
if (!appDetail)
@ -480,7 +480,9 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
/>
)}
{
showAccessControl && <AccessControl app={appDetail} onClose={() => { setShowAccessControl(false) }} />
showAccessControl && <AccessControl app={appDetail}
onConfirm={() => { setShowAccessControl(false) }}
onClose={() => { setShowAccessControl(false) }} />
}
</div>
</PortalToFollowElem>

View File

@ -1,7 +1,7 @@
'use client'
import { RiAlertFill, RiCloseCircleFill, RiLockLine, RiOrganizationChart } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { useEffect } from 'react'
import { useCallback, useEffect } from 'react'
import Avatar from '../../base/avatar'
import Divider from '../../base/divider'
import Tooltip from '../../base/tooltip'
@ -85,7 +85,13 @@ type GroupItemProps = {
group: AccessControlGroup
}
function GroupItem({ group }: GroupItemProps) {
return <BaseItem icon={<RiOrganizationChart className='w-[14px] h-[14px] text-components-avatar-shape-fill-stop-0' />}>
const specificGroups = useAccessControlStore(s => s.specificGroups)
const setSpecificGroups = useAccessControlStore(s => s.setSpecificGroups)
const handleRemoveGroup = useCallback(() => {
setSpecificGroups(specificGroups.filter(g => g.id !== group.id))
}, [group, setSpecificGroups, specificGroups])
return <BaseItem icon={<RiOrganizationChart className='w-[14px] h-[14px] text-components-avatar-shape-fill-stop-0' />}
onRemove={handleRemoveGroup}>
<p className='system-xs-regular text-text-primary'>{group.name}</p>
<p className='system-xs-regular text-text-tertiary'>{group.groupSize}</p>
</BaseItem>
@ -95,7 +101,13 @@ type MemberItemProps = {
member: AccessControlAccount
}
function MemberItem({ member }: MemberItemProps) {
return <BaseItem icon={<Avatar className='w-[14px] h-[14px]' textClassName='text-[12px]' avatar={null} name={member.name} />}>
const specificMembers = useAccessControlStore(s => s.specificMembers)
const setSpecificMembers = useAccessControlStore(s => s.setSpecificMembers)
const handleRemoveMember = useCallback(() => {
setSpecificMembers(specificMembers.filter(m => m.id !== member.id))
}, [member, setSpecificMembers, specificMembers])
return <BaseItem icon={<Avatar className='w-[14px] h-[14px]' textClassName='text-[12px]' avatar={null} name={member.name} />}
onRemove={handleRemoveMember}>
<p className='system-xs-regular text-text-primary'>{member.name}</p>
</BaseItem>
}
@ -103,8 +115,9 @@ function MemberItem({ member }: MemberItemProps) {
type BaseItemProps = {
icon: React.ReactNode
children: React.ReactNode
onRemove?: () => void
}
function BaseItem({ icon, children }: BaseItemProps) {
function BaseItem({ icon, onRemove, children }: BaseItemProps) {
return <div className='rounded-full border-[0.5px] bg-components-badge-white-to-dark shadow-xs p-1 pr-1.5 group flex items-center flex-row gap-x-1'>
<div className='w-5 h-5 rounded-full bg-components-icon-bg-blue-solid overflow-hidden'>
<div className='w-full h-full flex items-center justify-center bg-access-app-icon-mask-bg'>
@ -112,7 +125,7 @@ function BaseItem({ icon, children }: BaseItemProps) {
</div>
</div>
{children}
<div className='flex items-center justify-center w-4 h-4 cursor-pointer'>
<div className='flex items-center justify-center w-4 h-4 cursor-pointer' onClick={onRemove}>
<RiCloseCircleFill className='w-[14px] h-[14px] text-text-quaternary' />
</div>
</div>

View File

@ -512,7 +512,16 @@ export const ssePost = (
}).catch(() => {
res.json().then((data: any) => {
if (isPublicAPI) {
if (data.code === 'web_sso_auth_required' || data.code === 'web_app_access_denied')
if (data.code === 'web_app_access_denied') {
Toast.notify({
type: 'error',
message: data.message,
})
setTimeout(() => {
requiredWebSSOLogin()
}, 1500)
}
if (data.code === 'web_sso_auth_required')
requiredWebSSOLogin()
if (data.code === 'unauthorized') {
@ -566,7 +575,17 @@ export const request = async<T>(url: string, options = {}, otherOptions?: IOther
// special code
const { code, message } = errRespData
// webapp sso
if (code === 'web_sso_auth_required' || code === 'web_app_access_denied') {
if (code === 'web_app_access_denied') {
Toast.notify({
type: 'error',
message,
})
setTimeout(() => {
requiredWebSSOLogin()
}, 1500)
return Promise.reject(err)
}
if (code === 'web_sso_auth_required') {
requiredWebSSOLogin()
return Promise.reject(err)
}