Fix/webapp access scope (#20109)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { RiBuildingLine, RiGlobalLine } from '@remixicon/react'
|
||||
import { Description as DialogDescription, DialogTitle } from '@headlessui/react'
|
||||
import { RiBuildingLine, RiGlobalLine, RiVerifiedBadgeLine } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import Button from '../../base/button'
|
||||
@@ -67,8 +67,8 @@ export default function AccessControl(props: AccessControlProps) {
|
||||
return <AccessControlDialog show onClose={onClose}>
|
||||
<div className='flex flex-col gap-y-3'>
|
||||
<div className='pb-3 pl-6 pr-14 pt-6'>
|
||||
<Dialog.Title className='title-2xl-semi-bold text-text-primary'>{t('app.accessControlDialog.title')}</Dialog.Title>
|
||||
<Dialog.Description className='system-xs-regular mt-1 text-text-tertiary'>{t('app.accessControlDialog.description')}</Dialog.Description>
|
||||
<DialogTitle className='title-2xl-semi-bold text-text-primary'>{t('app.accessControlDialog.title')}</DialogTitle>
|
||||
<DialogDescription className='system-xs-regular mt-1 text-text-tertiary'>{t('app.accessControlDialog.description')}</DialogDescription>
|
||||
</div>
|
||||
<div className='flex flex-col gap-y-1 px-6 pb-3'>
|
||||
<div className='leading-6'>
|
||||
@@ -80,12 +80,20 @@ export default function AccessControl(props: AccessControlProps) {
|
||||
<RiBuildingLine className='h-4 w-4 text-text-primary' />
|
||||
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.organization')}</p>
|
||||
</div>
|
||||
{!hideTip && <WebAppSSONotEnabledTip />}
|
||||
</div>
|
||||
</AccessControlItem>
|
||||
<AccessControlItem type={AccessMode.SPECIFIC_GROUPS_MEMBERS}>
|
||||
<SpecificGroupsOrMembers />
|
||||
</AccessControlItem>
|
||||
<AccessControlItem type={AccessMode.EXTERNAL_MEMBERS}>
|
||||
<div className='flex items-center p-3'>
|
||||
<div className='flex grow items-center gap-x-2'>
|
||||
<RiVerifiedBadgeLine className='h-4 w-4 text-text-primary' />
|
||||
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.external')}</p>
|
||||
</div>
|
||||
{!hideTip && <WebAppSSONotEnabledTip />}
|
||||
</div>
|
||||
</AccessControlItem>
|
||||
<AccessControlItem type={AccessMode.PUBLIC}>
|
||||
<div className='flex items-center gap-x-2 p-3'>
|
||||
<RiGlobalLine className='h-4 w-4 text-text-primary' />
|
||||
|
||||
@@ -3,12 +3,10 @@ import { RiAlertFill, RiCloseCircleFill, RiLockLine, RiOrganizationChart } from
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import Avatar from '../../base/avatar'
|
||||
import Divider from '../../base/divider'
|
||||
import Tooltip from '../../base/tooltip'
|
||||
import Loading from '../../base/loading'
|
||||
import useAccessControlStore from '../../../../context/access-control-store'
|
||||
import AddMemberOrGroupDialog from './add-member-or-group-pop'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import type { AccessControlAccount, AccessControlGroup } from '@/models/access-control'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useAppWhiteListSubjects } from '@/service/access-control'
|
||||
@@ -19,11 +17,6 @@ export default function SpecificGroupsOrMembers() {
|
||||
const setSpecificGroups = useAccessControlStore(s => s.setSpecificGroups)
|
||||
const setSpecificMembers = useAccessControlStore(s => s.setSpecificMembers)
|
||||
const { t } = useTranslation()
|
||||
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||
const hideTip = systemFeatures.webapp_auth.enabled
|
||||
&& (systemFeatures.webapp_auth.allow_sso
|
||||
|| systemFeatures.webapp_auth.allow_email_password_login
|
||||
|| systemFeatures.webapp_auth.allow_email_code_login)
|
||||
|
||||
const { isPending, data } = useAppWhiteListSubjects(appId, Boolean(appId) && currentMenu === AccessMode.SPECIFIC_GROUPS_MEMBERS)
|
||||
useEffect(() => {
|
||||
@@ -37,7 +30,6 @@ export default function SpecificGroupsOrMembers() {
|
||||
<RiLockLine className='h-4 w-4 text-text-primary' />
|
||||
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||
</div>
|
||||
{!hideTip && <WebAppSSONotEnabledTip />}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -48,10 +40,6 @@ export default function SpecificGroupsOrMembers() {
|
||||
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||
</div>
|
||||
<div className='flex items-center gap-x-1'>
|
||||
{!hideTip && <>
|
||||
<WebAppSSONotEnabledTip />
|
||||
<Divider className='ml-2 mr-0 h-[14px]' type="vertical" />
|
||||
</>}
|
||||
<AddMemberOrGroupDialog />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,11 +9,14 @@ import dayjs from 'dayjs'
|
||||
import {
|
||||
RiArrowDownSLine,
|
||||
RiArrowRightSLine,
|
||||
RiBuildingLine,
|
||||
RiGlobalLine,
|
||||
RiLockLine,
|
||||
RiPlanetLine,
|
||||
RiPlayCircleLine,
|
||||
RiPlayList2Line,
|
||||
RiTerminalBoxLine,
|
||||
RiVerifiedBadgeLine,
|
||||
} from '@remixicon/react'
|
||||
import { useKeyPress } from 'ahooks'
|
||||
import { getKeyboardKeyCodeBySystem } from '../../workflow/utils'
|
||||
@@ -276,10 +279,30 @@ const AppPublisher = ({
|
||||
setShowAppAccessControl(true)
|
||||
}}>
|
||||
<div className='flex grow items-center gap-x-1.5 pr-1'>
|
||||
<RiLockLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
{appDetail?.access_mode === AccessMode.ORGANIZATION && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.organization')}</p>}
|
||||
{appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.specific')}</p>}
|
||||
{appDetail?.access_mode === AccessMode.PUBLIC && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.anyone')}</p>}
|
||||
{appDetail?.access_mode === AccessMode.ORGANIZATION
|
||||
&& <>
|
||||
<RiBuildingLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.organization')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS
|
||||
&& <>
|
||||
<RiLockLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.PUBLIC
|
||||
&& <>
|
||||
<RiGlobalLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.anyone')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.EXTERNAL_MEMBERS
|
||||
&& <>
|
||||
<RiVerifiedBadgeLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.external')}</p>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
{!isAppAccessSet && <p className='system-xs-regular shrink-0 text-text-tertiary'>{t('app.publishApp.notSet')}</p>}
|
||||
<div className='flex h-4 w-4 shrink-0 items-center justify-center'>
|
||||
|
||||
@@ -5,10 +5,13 @@ import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiArrowRightSLine,
|
||||
RiBookOpenLine,
|
||||
RiBuildingLine,
|
||||
RiEqualizer2Line,
|
||||
RiExternalLinkLine,
|
||||
RiGlobalLine,
|
||||
RiLockLine,
|
||||
RiPaintBrushLine,
|
||||
RiVerifiedBadgeLine,
|
||||
RiWindowLine,
|
||||
} from '@remixicon/react'
|
||||
import SettingsModal from './settings'
|
||||
@@ -248,11 +251,30 @@ function AppCard({
|
||||
<div className='flex h-9 w-full cursor-pointer items-center gap-x-0.5 rounded-lg bg-components-input-bg-normal py-1 pl-2.5 pr-2'
|
||||
onClick={handleClickAccessControl}>
|
||||
<div className='flex grow items-center gap-x-1.5 pr-1'>
|
||||
<RiLockLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
{appDetail?.access_mode === AccessMode.ORGANIZATION && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.organization')}</p>}
|
||||
{appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.specific')}</p>}
|
||||
{appDetail?.access_mode === AccessMode.PUBLIC && <p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.anyone')}</p>}
|
||||
</div>
|
||||
{appDetail?.access_mode === AccessMode.ORGANIZATION
|
||||
&& <>
|
||||
<RiBuildingLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.organization')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS
|
||||
&& <>
|
||||
<RiLockLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.PUBLIC
|
||||
&& <>
|
||||
<RiGlobalLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.anyone')}</p>
|
||||
</>
|
||||
}
|
||||
{appDetail?.access_mode === AccessMode.EXTERNAL_MEMBERS
|
||||
&& <>
|
||||
<RiVerifiedBadgeLine className='h-4 w-4 shrink-0 text-text-secondary' />
|
||||
<p className='system-sm-medium text-text-secondary'>{t('app.accessControlDialog.accessItems.external')}</p>
|
||||
</>
|
||||
}</div>
|
||||
{!isAppAccessSet && <p className='system-xs-regular shrink-0 text-text-tertiary'>{t('app.publishApp.notSet')}</p>}
|
||||
<div className='flex h-4 w-4 shrink-0 items-center justify-center'>
|
||||
<RiArrowRightSLine className='h-4 w-4 text-text-quaternary' />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use client'
|
||||
import classNames from '@/utils/classnames'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -7,17 +8,19 @@ type IAppUnavailableProps = {
|
||||
code?: number | string
|
||||
isUnknownReason?: boolean
|
||||
unknownReason?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const AppUnavailable: FC<IAppUnavailableProps> = ({
|
||||
code = 404,
|
||||
isUnknownReason,
|
||||
unknownReason,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex h-screen w-screen items-center justify-center'>
|
||||
<div className={classNames('flex h-screen w-screen items-center justify-center', className)}>
|
||||
<h1 className='mr-5 h-[50px] pr-5 text-[24px] font-medium leading-[50px]'
|
||||
style={{
|
||||
borderRight: '1px solid rgba(0,0,0,.3)',
|
||||
|
||||
@@ -16,14 +16,12 @@ import type {
|
||||
ConversationItem,
|
||||
} from '@/models/share'
|
||||
import { noop } from 'lodash-es'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
export type ChatWithHistoryContextValue = {
|
||||
appInfoError?: any
|
||||
appInfoLoading?: boolean
|
||||
appMeta?: AppMeta
|
||||
appData?: AppData
|
||||
accessMode?: AccessMode
|
||||
userCanAccess?: boolean
|
||||
appParams?: ChatConfig
|
||||
appChatListDataLoading?: boolean
|
||||
@@ -64,7 +62,6 @@ export type ChatWithHistoryContextValue = {
|
||||
}
|
||||
|
||||
export const ChatWithHistoryContext = createContext<ChatWithHistoryContextValue>({
|
||||
accessMode: AccessMode.SPECIFIC_GROUPS_MEMBERS,
|
||||
userCanAccess: false,
|
||||
currentConversationId: '',
|
||||
appPrevChatTree: [],
|
||||
|
||||
@@ -43,9 +43,8 @@ import { useAppFavicon } from '@/hooks/use-app-favicon'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
import { TransferMethod } from '@/types/app'
|
||||
import { noop } from 'lodash-es'
|
||||
import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
function getFormattedChatList(messages: any[]) {
|
||||
const newChatList: ChatItem[] = []
|
||||
@@ -77,11 +76,6 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
const isInstalledApp = useMemo(() => !!installedAppInfo, [installedAppInfo])
|
||||
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||
const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR(installedAppInfo ? null : 'appInfo', fetchAppInfo)
|
||||
const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode({
|
||||
appId: installedAppInfo?.app.id || appInfo?.app_id,
|
||||
isInstalledApp,
|
||||
enabled: systemFeatures.webapp_auth.enabled,
|
||||
})
|
||||
const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp({
|
||||
appId: installedAppInfo?.app.id || appInfo?.app_id,
|
||||
isInstalledApp,
|
||||
@@ -492,8 +486,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
|
||||
return {
|
||||
appInfoError,
|
||||
appInfoLoading: appInfoLoading || (systemFeatures.webapp_auth.enabled && (isGettingAccessMode || isCheckingPermission)),
|
||||
accessMode: systemFeatures.webapp_auth.enabled ? appAccessMode?.accessMode : AccessMode.PUBLIC,
|
||||
appInfoLoading: appInfoLoading || (systemFeatures.webapp_auth.enabled && isCheckingPermission),
|
||||
userCanAccess: systemFeatures.webapp_auth.enabled ? userCanAccessResult?.result : true,
|
||||
isInstalledApp,
|
||||
appId,
|
||||
|
||||
@@ -124,7 +124,6 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
|
||||
const {
|
||||
appInfoError,
|
||||
appInfoLoading,
|
||||
accessMode,
|
||||
userCanAccess,
|
||||
appData,
|
||||
appParams,
|
||||
@@ -169,7 +168,6 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
|
||||
appInfoError,
|
||||
appInfoLoading,
|
||||
appData,
|
||||
accessMode,
|
||||
userCanAccess,
|
||||
appParams,
|
||||
appMeta,
|
||||
|
||||
@@ -19,7 +19,6 @@ import RenameModal from '@/app/components/base/chat/chat-with-history/sidebar/re
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import type { ConversationItem } from '@/models/share'
|
||||
import cn from '@/utils/classnames'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
|
||||
type Props = {
|
||||
@@ -30,7 +29,6 @@ const Sidebar = ({ isPanel }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
isInstalledApp,
|
||||
accessMode,
|
||||
appData,
|
||||
handleNewConversation,
|
||||
pinnedConversationList,
|
||||
@@ -140,7 +138,7 @@ const Sidebar = ({ isPanel }: Props) => {
|
||||
)}
|
||||
</div>
|
||||
<div className='flex shrink-0 items-center justify-between p-3'>
|
||||
<MenuDropdown hideLogout={isInstalledApp || accessMode === AccessMode.PUBLIC} placement='top-start' data={appData?.site} />
|
||||
<MenuDropdown hideLogout={isInstalledApp} placement='top-start' data={appData?.site} />
|
||||
{/* powered by */}
|
||||
<div className='shrink-0'>
|
||||
{!appData?.custom_config?.remove_webapp_brand && (
|
||||
|
||||
@@ -15,10 +15,8 @@ import type {
|
||||
ConversationItem,
|
||||
} from '@/models/share'
|
||||
import { noop } from 'lodash-es'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
export type EmbeddedChatbotContextValue = {
|
||||
accessMode?: AccessMode
|
||||
userCanAccess?: boolean
|
||||
appInfoError?: any
|
||||
appInfoLoading?: boolean
|
||||
@@ -58,7 +56,6 @@ export type EmbeddedChatbotContextValue = {
|
||||
|
||||
export const EmbeddedChatbotContext = createContext<EmbeddedChatbotContextValue>({
|
||||
userCanAccess: false,
|
||||
accessMode: AccessMode.SPECIFIC_GROUPS_MEMBERS,
|
||||
currentConversationId: '',
|
||||
appPrevChatList: [],
|
||||
pinnedConversationList: [],
|
||||
|
||||
@@ -36,9 +36,8 @@ import { InputVarType } from '@/app/components/workflow/types'
|
||||
import { TransferMethod } from '@/types/app'
|
||||
import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils'
|
||||
import { noop } from 'lodash-es'
|
||||
import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
function getFormattedChatList(messages: any[]) {
|
||||
const newChatList: ChatItem[] = []
|
||||
@@ -70,11 +69,6 @@ export const useEmbeddedChatbot = () => {
|
||||
const isInstalledApp = false
|
||||
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||
const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR('appInfo', fetchAppInfo)
|
||||
const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode({
|
||||
appId: appInfo?.app_id,
|
||||
isInstalledApp,
|
||||
enabled: systemFeatures.webapp_auth.enabled,
|
||||
})
|
||||
const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp({
|
||||
appId: appInfo?.app_id,
|
||||
isInstalledApp,
|
||||
@@ -385,8 +379,7 @@ export const useEmbeddedChatbot = () => {
|
||||
|
||||
return {
|
||||
appInfoError,
|
||||
appInfoLoading: appInfoLoading || (systemFeatures.webapp_auth.enabled && (isGettingAccessMode || isCheckingPermission)),
|
||||
accessMode: systemFeatures.webapp_auth.enabled ? appAccessMode?.accessMode : AccessMode.PUBLIC,
|
||||
appInfoLoading: appInfoLoading || (systemFeatures.webapp_auth.enabled && isCheckingPermission),
|
||||
userCanAccess: systemFeatures.webapp_auth.enabled ? userCanAccessResult?.result : true,
|
||||
isInstalledApp,
|
||||
allowResetChat,
|
||||
|
||||
@@ -6,9 +6,8 @@ import type { Placement } from '@floating-ui/react'
|
||||
import {
|
||||
RiEqualizer2Line,
|
||||
} from '@remixicon/react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import Divider from '../../base/divider'
|
||||
import { removeAccessToken } from '../utils'
|
||||
import InfoModal from './info-modal'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import {
|
||||
@@ -19,6 +18,8 @@ import {
|
||||
import ThemeSwitcher from '@/app/components/base/theme-switcher'
|
||||
import type { SiteInfo } from '@/models/share'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
type Props = {
|
||||
data?: SiteInfo
|
||||
@@ -31,7 +32,9 @@ const MenuDropdown: FC<Props> = ({
|
||||
placement,
|
||||
hideLogout,
|
||||
}) => {
|
||||
const webAppAccessMode = useGlobalPublicStore(s => s.webAppAccessMode)
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const { t } = useTranslation()
|
||||
const [open, doSetOpen] = useState(false)
|
||||
const openRef = useRef(open)
|
||||
@@ -45,9 +48,10 @@ const MenuDropdown: FC<Props> = ({
|
||||
}, [setOpen])
|
||||
|
||||
const handleLogout = useCallback(() => {
|
||||
removeAccessToken()
|
||||
router.replace(`/webapp-signin?redirect_url=${window.location.href}`)
|
||||
}, [router])
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('webapp_access_token')
|
||||
router.replace(`/webapp-signin?redirect_url=${pathname}`)
|
||||
}, [router, pathname])
|
||||
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
@@ -92,6 +96,16 @@ const MenuDropdown: FC<Props> = ({
|
||||
className='system-md-regular cursor-pointer rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-base-hover'
|
||||
>{t('common.userProfile.about')}</div>
|
||||
</div>
|
||||
{!(hideLogout || webAppAccessMode === AccessMode.EXTERNAL_MEMBERS || webAppAccessMode === AccessMode.PUBLIC) && (
|
||||
<div className='p-1'>
|
||||
<div
|
||||
onClick={handleLogout}
|
||||
className='system-md-regular cursor-pointer rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-base-hover'
|
||||
>
|
||||
{t('common.userProfile.logout')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
|
||||
@@ -10,8 +10,8 @@ export const getInitialTokenV2 = (): Record<string, any> => ({
|
||||
version: 2,
|
||||
})
|
||||
|
||||
export const checkOrSetAccessToken = async () => {
|
||||
const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
export const checkOrSetAccessToken = async (appCode?: string) => {
|
||||
const sharedToken = appCode || globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
const userId = (await getProcessedSystemVariablesFromUrlParams()).user_id
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify(getInitialTokenV2())
|
||||
let accessTokenJson = getInitialTokenV2()
|
||||
@@ -23,8 +23,10 @@ export const checkOrSetAccessToken = async () => {
|
||||
catch {
|
||||
|
||||
}
|
||||
|
||||
if (!accessTokenJson[sharedToken]?.[userId || 'DEFAULT']) {
|
||||
const res = await fetchAccessToken(sharedToken, userId)
|
||||
const webAppAccessToken = localStorage.getItem('webapp_access_token')
|
||||
const res = await fetchAccessToken({ appCode: sharedToken, userId, webAppAccessToken })
|
||||
accessTokenJson[sharedToken] = {
|
||||
...accessTokenJson[sharedToken],
|
||||
[userId || 'DEFAULT']: res.access_token,
|
||||
@@ -33,7 +35,7 @@ export const checkOrSetAccessToken = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const setAccessToken = async (sharedToken: string, token: string, user_id?: string) => {
|
||||
export const setAccessToken = (sharedToken: string, token: string, user_id?: string) => {
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify(getInitialTokenV2())
|
||||
let accessTokenJson = getInitialTokenV2()
|
||||
try {
|
||||
@@ -69,6 +71,7 @@ export const removeAccessToken = () => {
|
||||
}
|
||||
|
||||
localStorage.removeItem(CONVERSATION_ID_INFO)
|
||||
localStorage.removeItem('webapp_access_token')
|
||||
|
||||
delete accessTokenJson[sharedToken]
|
||||
localStorage.setItem('token', JSON.stringify(accessTokenJson))
|
||||
|
||||
Reference in New Issue
Block a user