import {useContext} from 'react'
import {useReactOidc} from "@axa-fr/react-oidc-context";
import {ApiContext} from "../../services";
/**
* @typedef {object} ScopeCheckReturn
*/
type ScopeCheckReturn = {
/**
* Whether the logged in user has ALL of the provided scopes
*/
allScope: boolean
/**
* Whether the logged in user has ONE OR MORE of the provided scopes
*/
anyScope: boolean
/**
* Whether there is a user currently logged in (if no user is present, all return values are false)
*/
loggedIn: boolean
}
/**
* Custom hook for checking whether an OIDC user has the provided scopes.
*
* The hook can accept zero or more strings that represent the requested
* scopes, and returns a set of booleans representing the results.
*
* The three returned booleans are: `loggedIn`, `anyScope`, `allScope`
* - `loggedIn`: Whether there is a user currently logged in (if no user is present, all return values are false)
* - `anyScope`: Whether the logged in user has ONE OR MORE of the provided scopes
* - `allScope`: Whether the logged in user has ALL of the provided scopes
*
* The hook uses the {@link ApiManager}'s templating engine to match provided scopes to the current environment.
* This means you can provide generic scopes (e.g. an API interface scope) and it will templated to the
* correct environment equivalent.
*
*
* ### Hook Usage
*
* #### Checking if a user has a specific scope
* ```
* const {loggedIn, anyScope, allScope} = useScopeCheck('scope1')
* ```
* A single scope string can be checked against the scopes of the logged in user.
* In this use case `anyScope` and `allScope` are equivalent, a single scope will be true for both.
*
* #### Checking if a user has multiple scopes
* ```
* const {loggedIn, anyScope, allScope} = useScopeCheck(['scope1','scope2'])
* ```
* Multiple scope strings can be checked at once. In this use case `anyScope` will be true if the
* user has at least one and `allScope` will only be true if the user has all the provided scopes.
*
* #### Checking if a user is logged in
* ```
* const {loggedIn} = useScopeCheck()
* ```
* The hook can also be called without any scopes being provided. This can be used to check if a
* user is currently logged in or not.
*
* @category Hooks
* @module useScopeCheck
*
* @param [scopes] {string | string[]} The scope(s) to check against the current user
* @return {ScopeCheckReturn} The results of checking the scope(s)
*/
export function useScopeCheck(scopes: string | string[] | undefined): ScopeCheckReturn {
// Load oidcUser in case of scope props
let {oidcUser} = useReactOidc()
// Load apiManager for scope templating
let apiContext = useContext(ApiContext)
let allScope = false
let anyScope = false
let loggedIn = false
// Check if their is a user logged in
if (oidcUser) {
loggedIn = true
// If no scopes are provided, return the loggedIn value
if (scopes !== undefined) {
// Load scopes from the user
let {scope: returnedScopeString} = oidcUser
let returnedScopes = returnedScopeString.split(' ')
if (Array.isArray(scopes)) {
// Have to set allScope to true for the logic below to work
// (the length check keeps allScope false if scopes is an empty array)
allScope = scopes.length > 0
for (let specificScope of scopes) {
// Convert generic scope into templated scope, if in template format
// Leaves un-templated scopes unchanged
let templatedScope = apiContext.getTemplatedScope(specificScope)
allScope = allScope && returnedScopes.includes(templatedScope)
anyScope = anyScope || returnedScopes.includes(templatedScope)
}
} else {
// Convert generic scope into templated scope, if in template format
// Leaves un-templated scopes unchanged
let templatedScope = apiContext.getTemplatedScope(scopes)
allScope = returnedScopes.includes(templatedScope)
anyScope = returnedScopes.includes(templatedScope)
}
}
}
return {allScope, anyScope, loggedIn}
}
Source