| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import {
- createContext,
- useCallback,
- useContext,
- useState,
- useMemo,
- ReactNode,
- } from 'react'
- import { postJSON } from '../../../infrastructure/fetch-json'
- import useIsMounted from '../../../shared/hooks/use-is-mounted'
- import { set, cloneDeep } from 'lodash'
- import getMeta from '../../../utils/meta'
- import type {
- OAuthProviders,
- OAuthProvider,
- } from '../../../../../types/oauth-providers'
- import type { ThirdPartyIds } from '../../../../../types/third-party-ids'
- export type SSOSubscription = {
- providerId: string
- provider: OAuthProvider
- linked: boolean
- }
- type SSOContextValue = {
- subscriptions: Record<string, SSOSubscription>
- unlink: (id: string, signal?: AbortSignal) => Promise<void>
- }
- export const SSOContext = createContext<SSOContextValue | undefined>(undefined)
- type SSOProviderProps = {
- children: ReactNode
- }
- export function SSOProvider({ children }: SSOProviderProps) {
- const isMountedRef = useIsMounted()
- const oauthProviders = getMeta('ol-oauthProviders') as OAuthProviders
- const thirdPartyIds = getMeta('ol-thirdPartyIds') as ThirdPartyIds
- const [subscriptions, setSubscriptions] = useState<
- Record<string, SSOSubscription>
- >(() => {
- const initialSubscriptions: Record<string, SSOSubscription> = {}
- for (const [id, provider] of Object.entries(oauthProviders)) {
- const linked = !!thirdPartyIds[id]
- if (!provider.hideWhenNotLinked || linked) {
- initialSubscriptions[id] = {
- providerId: id,
- provider,
- linked,
- }
- }
- }
- return initialSubscriptions
- })
- const unlink = useCallback(
- (providerId: string, signal?: AbortSignal) => {
- if (!subscriptions[providerId].linked) {
- return Promise.resolve()
- }
- const body = {
- link: false,
- providerId,
- }
- return postJSON('/user/oauth-unlink', { body, signal }).then(() => {
- if (isMountedRef.current) {
- setSubscriptions(subs =>
- set(cloneDeep(subs), `${providerId}.linked`, false)
- )
- }
- })
- },
- [isMountedRef, subscriptions]
- )
- const value = useMemo<SSOContextValue>(
- () => ({
- subscriptions,
- unlink,
- }),
- [subscriptions, unlink]
- )
- return <SSOContext.Provider value={value}>{children}</SSOContext.Provider>
- }
- export function useSSOContext() {
- const context = useContext(SSOContext)
- if (!context) {
- throw new Error('SSOContext is only available inside SSOProvider')
- }
- return context
- }
|