@contember/react-identity 1.3.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/development/components/HasRole.cjs +24 -0
- package/dist/development/components/HasRole.cjs.map +1 -0
- package/dist/development/components/HasRole.js +24 -0
- package/dist/development/components/HasRole.js.map +1 -0
- package/dist/development/components/IdentityProvider.cjs +27 -0
- package/dist/development/components/IdentityProvider.cjs.map +1 -0
- package/dist/development/components/IdentityProvider.js +27 -0
- package/dist/development/components/IdentityProvider.js.map +1 -0
- package/dist/development/components/IdentityState.cjs +9 -0
- package/dist/development/components/IdentityState.cjs.map +1 -0
- package/dist/development/components/IdentityState.js +9 -0
- package/dist/development/components/IdentityState.js.map +1 -0
- package/dist/development/components/LogoutTrigger.cjs +12 -0
- package/dist/development/components/LogoutTrigger.cjs.map +1 -0
- package/dist/development/components/LogoutTrigger.js +12 -0
- package/dist/development/components/LogoutTrigger.js.map +1 -0
- package/dist/development/environment/IdentityEnvironmentExtension.cjs +13 -0
- package/dist/development/environment/IdentityEnvironmentExtension.cjs.map +1 -0
- package/dist/development/environment/IdentityEnvironmentExtension.js +13 -0
- package/dist/development/environment/IdentityEnvironmentExtension.js.map +1 -0
- package/dist/development/environment/ProjectEnvironmentExtension.cjs +13 -0
- package/dist/development/environment/ProjectEnvironmentExtension.cjs.map +1 -0
- package/dist/development/environment/ProjectEnvironmentExtension.js +13 -0
- package/dist/development/environment/ProjectEnvironmentExtension.js.map +1 -0
- package/dist/development/hooks/useFetchIdentity.cjs +51 -0
- package/dist/development/hooks/useFetchIdentity.cjs.map +1 -0
- package/dist/development/hooks/useFetchIdentity.js +51 -0
- package/dist/development/hooks/useFetchIdentity.js.map +1 -0
- package/dist/development/hooks/useLogout.cjs +10 -0
- package/dist/development/hooks/useLogout.cjs.map +1 -0
- package/dist/development/hooks/useLogout.js +10 -0
- package/dist/development/hooks/useLogout.js.map +1 -0
- package/dist/development/hooks/useProjectUserRoles.cjs +21 -0
- package/dist/development/hooks/useProjectUserRoles.cjs.map +1 -0
- package/dist/development/hooks/useProjectUserRoles.js +21 -0
- package/dist/development/hooks/useProjectUserRoles.js.map +1 -0
- package/dist/development/index.cjs +25 -0
- package/dist/development/index.cjs.map +1 -0
- package/dist/development/index.js +25 -0
- package/dist/development/index.js.map +1 -0
- package/dist/development/internal/contexts.cjs +13 -0
- package/dist/development/internal/contexts.cjs.map +1 -0
- package/dist/development/internal/contexts.js +13 -0
- package/dist/development/internal/contexts.js.map +1 -0
- package/dist/development/internal/hooks/useFetchMe.cjs +32 -0
- package/dist/development/internal/hooks/useFetchMe.cjs.map +1 -0
- package/dist/development/internal/hooks/useFetchMe.js +15 -0
- package/dist/development/internal/hooks/useFetchMe.js.map +1 -0
- package/dist/development/internal/hooks/useLogoutInternal.cjs +35 -0
- package/dist/development/internal/hooks/useLogoutInternal.cjs.map +1 -0
- package/dist/development/internal/hooks/useLogoutInternal.js +35 -0
- package/dist/development/internal/hooks/useLogoutInternal.js.map +1 -0
- package/dist/development/internal/hooks/useSignOut.cjs +30 -0
- package/dist/development/internal/hooks/useSignOut.cjs.map +1 -0
- package/dist/development/internal/hooks/useSignOut.js +13 -0
- package/dist/development/internal/hooks/useSignOut.js.map +1 -0
- package/dist/production/components/HasRole.cjs +24 -0
- package/dist/production/components/HasRole.cjs.map +1 -0
- package/dist/production/components/HasRole.js +24 -0
- package/dist/production/components/HasRole.js.map +1 -0
- package/dist/production/components/IdentityProvider.cjs +27 -0
- package/dist/production/components/IdentityProvider.cjs.map +1 -0
- package/dist/production/components/IdentityProvider.js +27 -0
- package/dist/production/components/IdentityProvider.js.map +1 -0
- package/dist/production/components/IdentityState.cjs +9 -0
- package/dist/production/components/IdentityState.cjs.map +1 -0
- package/dist/production/components/IdentityState.js +9 -0
- package/dist/production/components/IdentityState.js.map +1 -0
- package/dist/production/components/LogoutTrigger.cjs +12 -0
- package/dist/production/components/LogoutTrigger.cjs.map +1 -0
- package/dist/production/components/LogoutTrigger.js +12 -0
- package/dist/production/components/LogoutTrigger.js.map +1 -0
- package/dist/production/environment/IdentityEnvironmentExtension.cjs +13 -0
- package/dist/production/environment/IdentityEnvironmentExtension.cjs.map +1 -0
- package/dist/production/environment/IdentityEnvironmentExtension.js +13 -0
- package/dist/production/environment/IdentityEnvironmentExtension.js.map +1 -0
- package/dist/production/environment/ProjectEnvironmentExtension.cjs +13 -0
- package/dist/production/environment/ProjectEnvironmentExtension.cjs.map +1 -0
- package/dist/production/environment/ProjectEnvironmentExtension.js +13 -0
- package/dist/production/environment/ProjectEnvironmentExtension.js.map +1 -0
- package/dist/production/hooks/useFetchIdentity.cjs +51 -0
- package/dist/production/hooks/useFetchIdentity.cjs.map +1 -0
- package/dist/production/hooks/useFetchIdentity.js +51 -0
- package/dist/production/hooks/useFetchIdentity.js.map +1 -0
- package/dist/production/hooks/useLogout.cjs +10 -0
- package/dist/production/hooks/useLogout.cjs.map +1 -0
- package/dist/production/hooks/useLogout.js +10 -0
- package/dist/production/hooks/useLogout.js.map +1 -0
- package/dist/production/hooks/useProjectUserRoles.cjs +21 -0
- package/dist/production/hooks/useProjectUserRoles.cjs.map +1 -0
- package/dist/production/hooks/useProjectUserRoles.js +21 -0
- package/dist/production/hooks/useProjectUserRoles.js.map +1 -0
- package/dist/production/index.cjs +25 -0
- package/dist/production/index.cjs.map +1 -0
- package/dist/production/index.js +25 -0
- package/dist/production/index.js.map +1 -0
- package/dist/production/internal/contexts.cjs +13 -0
- package/dist/production/internal/contexts.cjs.map +1 -0
- package/dist/production/internal/contexts.js +13 -0
- package/dist/production/internal/contexts.js.map +1 -0
- package/dist/production/internal/hooks/useFetchMe.cjs +32 -0
- package/dist/production/internal/hooks/useFetchMe.cjs.map +1 -0
- package/dist/production/internal/hooks/useFetchMe.js +15 -0
- package/dist/production/internal/hooks/useFetchMe.js.map +1 -0
- package/dist/production/internal/hooks/useLogoutInternal.cjs +35 -0
- package/dist/production/internal/hooks/useLogoutInternal.cjs.map +1 -0
- package/dist/production/internal/hooks/useLogoutInternal.js +35 -0
- package/dist/production/internal/hooks/useLogoutInternal.js.map +1 -0
- package/dist/production/internal/hooks/useSignOut.cjs +30 -0
- package/dist/production/internal/hooks/useSignOut.cjs.map +1 -0
- package/dist/production/internal/hooks/useSignOut.js +13 -0
- package/dist/production/internal/hooks/useSignOut.js.map +1 -0
- package/dist/types/components/HasRole.d.ts +11 -0
- package/dist/types/components/HasRole.d.ts.map +1 -0
- package/dist/types/components/IdentityProvider.d.ts +6 -0
- package/dist/types/components/IdentityProvider.d.ts.map +1 -0
- package/dist/types/components/IdentityState.d.ts +8 -0
- package/dist/types/components/IdentityState.d.ts.map +1 -0
- package/dist/types/components/LogoutTrigger.d.ts +5 -0
- package/dist/types/components/LogoutTrigger.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +5 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/types/environment/IdentityEnvironmentExtension.d.ts +6 -0
- package/dist/types/environment/IdentityEnvironmentExtension.d.ts.map +1 -0
- package/dist/types/environment/ProjectEnvironmentExtension.d.ts +5 -0
- package/dist/types/environment/ProjectEnvironmentExtension.d.ts.map +1 -0
- package/dist/types/environment/index.d.ts +3 -0
- package/dist/types/environment/index.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +5 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useFetchIdentity.d.ts +6 -0
- package/dist/types/hooks/useFetchIdentity.d.ts.map +1 -0
- package/dist/types/hooks/useLogout.d.ts +4 -0
- package/dist/types/hooks/useLogout.d.ts.map +1 -0
- package/dist/types/hooks/useProjectUserRoles.d.ts +3 -0
- package/dist/types/hooks/useProjectUserRoles.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/internal/contexts.d.ts +7 -0
- package/dist/types/internal/contexts.d.ts.map +1 -0
- package/dist/types/internal/hooks/useFetchMe.d.ts +94 -0
- package/dist/types/internal/hooks/useFetchMe.d.ts.map +1 -0
- package/dist/types/internal/hooks/useLogoutInternal.d.ts +4 -0
- package/dist/types/internal/hooks/useLogoutInternal.d.ts.map +1 -0
- package/dist/types/internal/hooks/useSignOut.d.ts +26 -0
- package/dist/types/internal/hooks/useSignOut.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/dist/types/types/Identity.d.ts +19 -0
- package/dist/types/types/Identity.d.ts.map +1 -0
- package/dist/types/types/IdentityMethods.d.ts +5 -0
- package/dist/types/types/IdentityMethods.d.ts.map +1 -0
- package/dist/types/types/IdentityStateValue.d.ts +2 -0
- package/dist/types/types/IdentityStateValue.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +4 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/package.json +58 -0
- package/src/components/HasRole.tsx +33 -0
- package/src/components/IdentityProvider.tsx +40 -0
- package/src/components/IdentityState.tsx +14 -0
- package/src/components/LogoutTrigger.tsx +10 -0
- package/src/components/index.ts +4 -0
- package/src/environment/IdentityEnvironmentExtension.ts +12 -0
- package/src/environment/ProjectEnvironmentExtension.tsx +10 -0
- package/src/environment/index.ts +2 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/useFetchIdentity.ts +54 -0
- package/src/hooks/useLogout.ts +7 -0
- package/src/hooks/useProjectUserRoles.tsx +21 -0
- package/src/index.ts +4 -0
- package/src/internal/contexts.ts +8 -0
- package/src/internal/hooks/useFetchMe.ts +21 -0
- package/src/internal/hooks/useLogoutInternal.ts +35 -0
- package/src/internal/hooks/useSignOut.ts +13 -0
- package/src/tsconfig.json +12 -0
- package/src/types/Identity.ts +20 -0
- package/src/types/IdentityMethods.ts +4 -0
- package/src/types/IdentityStateValue.ts +6 -0
- package/src/types/index.ts +3 -0
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@contember/react-identity",
|
|
3
|
+
"license": "Apache-2.0",
|
|
4
|
+
"version": "1.3.0-alpha.14",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/production/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/types/index.d.ts",
|
|
12
|
+
"development": "./dist/development/index.js",
|
|
13
|
+
"production": "./dist/production/index.js",
|
|
14
|
+
"default": "./dist/production/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/types/index.d.ts",
|
|
18
|
+
"development": "./dist/development/index.cjs",
|
|
19
|
+
"production": "./dist/production/index.cjs",
|
|
20
|
+
"default": "./dist/production/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/",
|
|
26
|
+
"src/"
|
|
27
|
+
],
|
|
28
|
+
"typings": "./dist/types/index.d.ts",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "yarn build:js:dev && yarn build:js:prod",
|
|
31
|
+
"build:js:dev": "vite build --mode development",
|
|
32
|
+
"build:js:prod": "vite build --mode production",
|
|
33
|
+
"ae:build": "api-extractor run --local",
|
|
34
|
+
"ae:test": "api-extractor run",
|
|
35
|
+
"test": "vitest"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/contember/interface.git",
|
|
40
|
+
"directory": "packages/react-identity"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@contember/react-binding": "1.3.0-alpha.14",
|
|
44
|
+
"@contember/react-client": "1.3.0-alpha.14",
|
|
45
|
+
"@contember/react-client-tenant": "1.3.0-alpha.14",
|
|
46
|
+
"@contember/react-utils": "1.3.0-alpha.14",
|
|
47
|
+
"@radix-ui/react-slot": "^1.0.2"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"react": "^17 || ^18",
|
|
51
|
+
"react-dom": "^17 || ^18"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"react": "^18.2.0",
|
|
55
|
+
"react-dom": "^18.2.0"
|
|
56
|
+
},
|
|
57
|
+
"stableVersion": "0.0.0"
|
|
58
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Component } from '@contember/react-binding'
|
|
2
|
+
import { ReactNode } from 'react'
|
|
3
|
+
import { useProjectUserRoles } from '../hooks'
|
|
4
|
+
import { identityEnvironmentExtension, projectEnvironmentExtension } from '../environment'
|
|
5
|
+
|
|
6
|
+
export type RoleCondition = string | ((roles: Set<string>) => boolean)
|
|
7
|
+
|
|
8
|
+
export interface HasRoleProps {
|
|
9
|
+
children?: ReactNode
|
|
10
|
+
role: RoleCondition
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @group Logic Components
|
|
15
|
+
*/
|
|
16
|
+
export const HasRole = Component<HasRoleProps>(({ children, role }) => {
|
|
17
|
+
const projectRoles = useProjectUserRoles()
|
|
18
|
+
|
|
19
|
+
return evaluateCondition(role, projectRoles) ? <>{children}</> : null
|
|
20
|
+
}, ({ children, role }, env) => {
|
|
21
|
+
const identity = env.getExtension(identityEnvironmentExtension).identity
|
|
22
|
+
const project = env.getExtension(projectEnvironmentExtension).slug
|
|
23
|
+
const projectRoles = new Set(identity?.projects.find(it => it.slug === project)?.roles ?? [])
|
|
24
|
+
|
|
25
|
+
return evaluateCondition(role, projectRoles) ? <>{children}</> : null
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const evaluateCondition = (condition: RoleCondition, roles: Set<string>) => {
|
|
29
|
+
if (typeof condition === 'string') {
|
|
30
|
+
return roles.has(condition)
|
|
31
|
+
}
|
|
32
|
+
return condition(roles)
|
|
33
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useSessionToken } from '@contember/react-client'
|
|
2
|
+
import { ReactNode, useEffect } from 'react'
|
|
3
|
+
import { EnvironmentExtensionProvider } from '@contember/react-binding'
|
|
4
|
+
import { useFetchIdentity } from '../hooks'
|
|
5
|
+
import { IdentityContext, IdentityMethodsContext, IdentityStateContext } from '../internal/contexts'
|
|
6
|
+
import { identityEnvironmentExtension } from '../environment/IdentityEnvironmentExtension'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export interface IdentityProviderProps {
|
|
10
|
+
children: ReactNode
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const IdentityProvider: React.FC<IdentityProviderProps> = ({ children }) => {
|
|
14
|
+
const sessionToken = useSessionToken()
|
|
15
|
+
const [{ identity, state }, methods] = useFetchIdentity()
|
|
16
|
+
|
|
17
|
+
const { refreshIdentity, clearIdentity } = methods
|
|
18
|
+
useEffect(
|
|
19
|
+
() => {
|
|
20
|
+
if (sessionToken !== undefined) {
|
|
21
|
+
refreshIdentity()
|
|
22
|
+
} else {
|
|
23
|
+
clearIdentity()
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
[sessionToken, refreshIdentity, clearIdentity],
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<IdentityStateContext.Provider value={state}>
|
|
31
|
+
<IdentityContext.Provider value={identity}>
|
|
32
|
+
<IdentityMethodsContext.Provider value={methods}>
|
|
33
|
+
<EnvironmentExtensionProvider extension={identityEnvironmentExtension} state={identity ?? null}>
|
|
34
|
+
{children}
|
|
35
|
+
</EnvironmentExtensionProvider>
|
|
36
|
+
</IdentityMethodsContext.Provider>
|
|
37
|
+
</IdentityContext.Provider>
|
|
38
|
+
</IdentityStateContext.Provider>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react'
|
|
2
|
+
import { IdentityStateValue } from '../types'
|
|
3
|
+
import { useIdentityState } from '../internal/contexts'
|
|
4
|
+
|
|
5
|
+
export interface IdentityStateProps {
|
|
6
|
+
state: IdentityStateValue | IdentityStateValue[]
|
|
7
|
+
children: ReactNode
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const IdentityState = ({ state, children }: IdentityStateProps) => {
|
|
11
|
+
const currentState = useIdentityState()
|
|
12
|
+
|
|
13
|
+
return state === currentState || (Array.isArray(state) && state.includes(currentState)) ? children : null
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode, useCallback } from 'react'
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot'
|
|
3
|
+
import { useLogout } from '../hooks'
|
|
4
|
+
|
|
5
|
+
export const LogoutTrigger = ({ children }: {
|
|
6
|
+
children: ReactNode
|
|
7
|
+
}) => {
|
|
8
|
+
const logout = useLogout()
|
|
9
|
+
return <Slot onClick={useCallback(() => logout(), [logout])}>{children}</Slot>
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BindingError, Environment } from '@contember/react-binding'
|
|
2
|
+
import { Identity } from '../types'
|
|
3
|
+
|
|
4
|
+
export const identityEnvironmentExtension = Environment.createExtension((state: Identity | null | undefined) => {
|
|
5
|
+
if (state === undefined) {
|
|
6
|
+
throw new BindingError('Environment does not contain identity state.')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
identity: state ?? undefined,
|
|
11
|
+
}
|
|
12
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BindingError, Environment } from '@contember/react-binding'
|
|
2
|
+
|
|
3
|
+
export const projectEnvironmentExtension = Environment.createExtension((slug: string | null | undefined) => {
|
|
4
|
+
if (slug === undefined) {
|
|
5
|
+
throw new BindingError('Environment does not contain project slug state.')
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
slug: slug ?? undefined,
|
|
9
|
+
}
|
|
10
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react'
|
|
2
|
+
import { Identity, IdentityMethods, IdentityStateValue } from '../types'
|
|
3
|
+
import { useSessionToken } from '@contember/react-client'
|
|
4
|
+
import { useFetchMe } from '../internal/hooks/useFetchMe'
|
|
5
|
+
import { useLogoutInternal } from '../internal/hooks/useLogoutInternal'
|
|
6
|
+
|
|
7
|
+
export const useFetchIdentity = (): [{ state: IdentityStateValue, identity: Identity | undefined }, IdentityMethods] => {
|
|
8
|
+
const sessionToken = useSessionToken()
|
|
9
|
+
const fetchMe = useFetchMe()
|
|
10
|
+
|
|
11
|
+
const [identityState, setIdentityState] = useState<IdentityStateValue>(sessionToken ? 'loading' : 'none')
|
|
12
|
+
const [identity, setIdentity] = useState<Identity | undefined>()
|
|
13
|
+
|
|
14
|
+
const clearIdentity = useCallback(() => setIdentityState('cleared'), [])
|
|
15
|
+
const logout = useLogoutInternal(clearIdentity)
|
|
16
|
+
|
|
17
|
+
const fetch = useCallback(async () => {
|
|
18
|
+
setIdentityState('loading')
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetchMe()
|
|
21
|
+
const person = response.person
|
|
22
|
+
const projects = response.projects
|
|
23
|
+
const permissions = response.permissions ?? { canCreateProject: false }
|
|
24
|
+
|
|
25
|
+
setIdentityState('success')
|
|
26
|
+
setIdentity({
|
|
27
|
+
id: response.id,
|
|
28
|
+
person: person ?? undefined,
|
|
29
|
+
projects: projects.map(it => ({
|
|
30
|
+
name: it.project.name,
|
|
31
|
+
slug: it.project.slug,
|
|
32
|
+
roles: it.memberships.map(it => it.role),
|
|
33
|
+
})),
|
|
34
|
+
permissions,
|
|
35
|
+
})
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.error(e)
|
|
38
|
+
if (typeof e === 'object' && e !== null && 'status' in e && (e as { status?: unknown }).status === 401) {
|
|
39
|
+
logout({ noRedirect: true })
|
|
40
|
+
setIdentityState('cleared')
|
|
41
|
+
} else {
|
|
42
|
+
setIdentityState('failed')
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, [fetchMe, logout])
|
|
46
|
+
|
|
47
|
+
return [
|
|
48
|
+
{ state: identityState, identity },
|
|
49
|
+
useMemo((): IdentityMethods => ({
|
|
50
|
+
clearIdentity,
|
|
51
|
+
refreshIdentity: fetch,
|
|
52
|
+
}), [clearIdentity, fetch]),
|
|
53
|
+
]
|
|
54
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import { useProjectSlug } from '@contember/react-client'
|
|
3
|
+
import { useIdentity } from '../internal/contexts'
|
|
4
|
+
|
|
5
|
+
export type ProjectUserRoles = Set<string>
|
|
6
|
+
|
|
7
|
+
export const useProjectUserRoles = (): ProjectUserRoles => {
|
|
8
|
+
const identity = useIdentity()
|
|
9
|
+
const projectSlug = useProjectSlug()
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
if (!projectSlug) {
|
|
12
|
+
return new Set()
|
|
13
|
+
}
|
|
14
|
+
const targetProject = identity?.projects.find(project => project.slug === projectSlug)
|
|
15
|
+
if (targetProject === undefined) {
|
|
16
|
+
return new Set()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return new Set(targetProject.roles)
|
|
20
|
+
}, [identity?.projects, projectSlug])
|
|
21
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createContext, createRequiredContext } from '@contember/react-utils'
|
|
2
|
+
import { IdentityMethods } from '../types/IdentityMethods'
|
|
3
|
+
import { Identity } from '../types/Identity'
|
|
4
|
+
import { IdentityStateValue } from '../types/IdentityStateValue'
|
|
5
|
+
|
|
6
|
+
export const [IdentityContext, useIdentity] = createContext<Identity | undefined>('IdentityContext', undefined)
|
|
7
|
+
export const [IdentityMethodsContext, useIdentityMethods] = createRequiredContext<IdentityMethods>('IdentityMethodsContext')
|
|
8
|
+
export const [IdentityStateContext, useIdentityState] = createRequiredContext<IdentityStateValue>('IdentityStateContext')
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as TenantApi from '@contember/react-client-tenant'
|
|
2
|
+
import { useCallback } from 'react'
|
|
3
|
+
|
|
4
|
+
const identityFragment = TenantApi
|
|
5
|
+
.identity$$
|
|
6
|
+
.person(TenantApi.person$$)
|
|
7
|
+
.projects(TenantApi
|
|
8
|
+
.identityProjectRelation$
|
|
9
|
+
.project(TenantApi.project$$)
|
|
10
|
+
.memberships(TenantApi.membership$$.variables(TenantApi.variableEntry$$)),
|
|
11
|
+
)
|
|
12
|
+
.permissions(TenantApi.identityGlobalPermissions$$)
|
|
13
|
+
|
|
14
|
+
export type FetchedIdentity = TenantApi.ModelType<typeof identityFragment>
|
|
15
|
+
|
|
16
|
+
export const useFetchMe = () => {
|
|
17
|
+
const executor = TenantApi.useTenantApi()
|
|
18
|
+
return useCallback(async () => {
|
|
19
|
+
return (await executor(TenantApi.query$.me(identityFragment))).me
|
|
20
|
+
}, [executor])
|
|
21
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useSetSessionToken } from '@contember/react-client'
|
|
2
|
+
import { useCallback } from 'react'
|
|
3
|
+
import { useSignOut } from './useSignOut'
|
|
4
|
+
|
|
5
|
+
export const useLogoutInternal = (clearIdentity?: () => void) => {
|
|
6
|
+
const tenantLogout = useSignOut()
|
|
7
|
+
const setSessionToken = useSetSessionToken()
|
|
8
|
+
|
|
9
|
+
return useCallback(
|
|
10
|
+
async ({ noRedirect = false }: { noRedirect?: boolean } = {}) => {
|
|
11
|
+
if (navigator.credentials && navigator.credentials.preventSilentAccess) {
|
|
12
|
+
try {
|
|
13
|
+
await navigator.credentials.preventSilentAccess()
|
|
14
|
+
} catch {
|
|
15
|
+
// actually, not implemented in safari:
|
|
16
|
+
// https://github.com/WebKit/WebKit/blob/414f4e45b0e82bbfcee783d08a9642be1afa8f72/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp#L132
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
clearIdentity?.()
|
|
20
|
+
setSessionToken(undefined)
|
|
21
|
+
try {
|
|
22
|
+
const response = await tenantLogout()
|
|
23
|
+
if (!response?.ok) {
|
|
24
|
+
console.warn(response?.error)
|
|
25
|
+
}
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.warn(e)
|
|
28
|
+
}
|
|
29
|
+
if (!noRedirect) {
|
|
30
|
+
window.location.href = '/' // todo better redirect?
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
[clearIdentity, setSessionToken, tenantLogout],
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as TenantApi from '@contember/react-client-tenant'
|
|
2
|
+
import { useCallback } from 'react'
|
|
3
|
+
|
|
4
|
+
const signOutFragment = TenantApi.signOutResponse$$.error(TenantApi.signOutError$$)
|
|
5
|
+
|
|
6
|
+
export type SignOutResult = TenantApi.ModelType<typeof signOutFragment>
|
|
7
|
+
|
|
8
|
+
export const useSignOut = () => {
|
|
9
|
+
const api = TenantApi.useTenantApi()
|
|
10
|
+
return useCallback(async () => {
|
|
11
|
+
return (await api(TenantApi.mutation$.signOut(signOutFragment))).signOut
|
|
12
|
+
}, [api])
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../tsconfig.settings.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../dist/types"
|
|
5
|
+
},
|
|
6
|
+
"references": [
|
|
7
|
+
{ "path": "../../react-binding/src" },
|
|
8
|
+
{ "path": "../../react-client/src" },
|
|
9
|
+
{ "path": "../../react-client-tenant/src" },
|
|
10
|
+
{ "path": "../../react-utils/src" },
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface Identity {
|
|
2
|
+
readonly id: string
|
|
3
|
+
readonly person?: Person
|
|
4
|
+
readonly projects: IdentityProject[]
|
|
5
|
+
readonly permissions: {
|
|
6
|
+
readonly canCreateProject: boolean
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Person {
|
|
11
|
+
readonly id: string
|
|
12
|
+
readonly email?: string
|
|
13
|
+
readonly otpEnabled: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface IdentityProject {
|
|
17
|
+
readonly slug: string
|
|
18
|
+
readonly name: string
|
|
19
|
+
readonly roles: readonly string[]
|
|
20
|
+
}
|