Auth Context
This services fetches, stores, and maintains the authentication context for the currently logged in user.
Examples
Getting the Auth Context
The auth context can be synchronously retrieved using getAuthContext.
import { getAuthContext } from '@rhapsody/auth-context'
function getUserGuid() {
const { user } = getAuthContext()
return user.guid
}
Subscribing to the Auth Context
We can subscribe to the auth context and receive updates if it changes over time subscribeToAuthContext.
import { subscribeToAuthContext } from '@rhapsody/auth-context'
subscribeToAuthContext((authContext) => {
console.log(authContext)
})
When subscribeToAuthContext is called, the callback will be fired immediately with the current value of the auth context.
Reading the Auth Context in React
import { useAuthContext } from '@rhapsody/auth-context'
function TeamName() {
const { team } = useAuthContext()
return <span>{team.name}</span>
}
Refreshing the Auth Context
There may be situations where the auth context needs to be updated. For example, the current user might change their timezone. In this situation, the auth context can be refreshed using refreshAuthContext.
import { refreshAuthContext } from '@rhapsody/auth-context'
async function updateUserData() {
// ...
const refreshedSuccessfully = await refreshAuthContext()
// ...
}
refreshAuthContext does not return the value of the refreshed auth context. It returns a boolean representing whether the auth context was successfully refreshed. To get the updated auth context value, use getAuthContext or subscribe to changes.
Getting User Entitlements
Use the hasFeature function to determine if the current user has access to a feature.
import { hasFeature } from '@rhapsody/auth-context'
if (hasFeature('cadence')) {
// ...
}
Use the hasEntitlement function to determine if the current user has access to an entitlement specific to a feature.
import { hasEntitlement } from '@rhapsody/auth-context'
if (hasEntitlement('meeting_intelligence', 'unlimited_lifetime_recording')) {
// ...
}
Testing
This package has a mock in place for use with jest.mock. When mocked, the auth context is populated with the fixtures in ./src/__data__/fixtures.ts, with the one exception that user.isImpersonating defaults to false. A special function _setMockData is available when mocking the auth context that allows you to override the defaults with any partial set of auth context data. For example, calling _setMockData({ team: { planFeatures: { newFeature: 'New Feature' }}}) deeply merges team.planFeatures.newFeature into the default data.
See the example below to on how to test code that utilizes the auth context:
import React from 'react'
import { render, screen } from '@testing-library/react'
import { useAuthContext, _setMockData } from '@rhapsody/auth-context'
// BEGIN CODE REQUIRED TO MOCK AUTH CONTEXT
jest.mock('@rhapsody/auth-context')
beforeEach(() => {
// Using this function without any overrides resets the mock data back to its
// default state
_setMockData()
})
// END CODE REQUIRED TO MOCK AUTH CONTEXT
function ComponentToTest() {
const { user } = useAuthContext()
if (user.isImpersonating) return <span>Incognito</span>
return <span>User</span>
}
describe('ComponentToTest', () => {
it('displays "User" when the current user is not impersonating', () => {
render(<MyComponent />)
expect(screen.queryByText('User')).toBeInTheDocument()
})
it('displays "Incognito" when the current user is impersonating', () => {
_setMockData({ user: { isImpersonating: true } })
render(<MyComponent />)
expect(screen.queryByText('User')).toBeInTheDocument()
})
})
Note: the _setMockData export is only available when mocking the auth context. It is not a part of the regular auth context package and does not work unless jest.mock('@rhapsody/auth-context') is invoked.
Updating the AuthContext Contract
If new fields are added to the /me or /team API endpoints, they are not automatically added to the auth context. This must be done manually. For most use cases, fields can be added to the auth context by following these steps:
- Update the appropriate interfaces in
src/types.ts, including documentation for the new field(s) - Update the data fixtures in
src/__data__/fixtures.ts - Update the convert functions in
src/api.tse.g.convertApiUserToUserandconvertApiTeamToTeam
Initialization
Advanced
The auth context should only be initialized once when the application first boots. Subsequent attempts to initialize it will throw an error.
import { initAuthContext } from '@rhapsody/auth-context'
async function boot() {
// These values are passed into the auth context. They are not available in the public API endpoints.
const isImpersonating = checkIsImpersonating()
const isSsoAdmin = checkIsSsoAdmin()
const initializedSuccessfully = await initAuthContext({
isImpersonating,
isSsoAdmin,
})
// ...
}