Skip to content

Commit

Permalink
store cookie prefs in a cookie for cross-site support
Browse files Browse the repository at this point in the history
  • Loading branch information
jay-hodgson committed Jun 25, 2024
1 parent f55fae2 commit 8efffd5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Meta, StoryObj } from '@storybook/react'
import React from 'react'
import CookiesNotification from './CookiesNotification'
import { COOKIES_AGREEMENT_LOCALSTORAGE_KEY } from '../../utils/hooks/useCookiePreferences'
import UniversalCookies from 'universal-cookie'
import { COOKIES_AGREEMENT_COOKIE_KEY } from '../../utils/hooks/useCookiePreferences'

const cookies = new UniversalCookies()

const meta = {
title: 'UI/CookiesNotification',
component: CookiesNotification,
render: () => {
localStorage.removeItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY)
cookies.remove(COOKIES_AGREEMENT_COOKIE_KEY)
return (
<CookiesNotification
onClose={prefs => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import React from 'react'
import { createWrapper } from '../../testutils/TestingLibraryUtils'
import { SynapseContextType } from '../../utils/context/SynapseContext'
import CookiesNotification, { alertConfig } from './CookiesNotification'
import UniversalCookies from 'universal-cookie'
import {
COOKIES_AGREEMENT_LOCALSTORAGE_KEY,
COOKIES_AGREEMENT_COOKIE_KEY,
CookiePreference,
} from '../../utils/hooks/useCookiePreferences'

const cookies = new UniversalCookies()
const mockOnCloseFn = jest.fn()
function renderComponent(wrapperProps?: SynapseContextType) {
const component = render(<CookiesNotification onClose={mockOnCloseFn} />, {
Expand All @@ -23,8 +25,7 @@ describe('CookiesNotification', () => {
jest.clearAllMocks()
})
afterEach(() => {
localStorage.getItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY) &&
localStorage.removeItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY)
cookies.remove(COOKIES_AGREEMENT_COOKIE_KEY)
})

it('displays alert and allows user to accept all cookies', async () => {
Expand All @@ -40,11 +41,10 @@ describe('CookiesNotification', () => {
await user.click(acceptButton)

expect(alert).not.toBeInTheDocument()
const localStorageValue = localStorage.getItem(
COOKIES_AGREEMENT_LOCALSTORAGE_KEY,
)
expect(localStorageValue).toBeDefined()
const cookiePreference = JSON.parse(localStorageValue!) as CookiePreference
const cookiePreference = cookies.get(
COOKIES_AGREEMENT_COOKIE_KEY,
) as CookiePreference
expect(cookiePreference).toBeDefined()
expect(cookiePreference.analyticsAllowed).toBe(true)
expect(cookiePreference.functionalAllowed).toBe(true)
})
Expand All @@ -62,11 +62,10 @@ describe('CookiesNotification', () => {
await user.click(disableAllButton)

expect(alert).not.toBeInTheDocument()
const localStorageValue = localStorage.getItem(
COOKIES_AGREEMENT_LOCALSTORAGE_KEY,
)
expect(localStorageValue).toBeDefined()
const cookiePreference = JSON.parse(localStorageValue!) as CookiePreference
const cookiePreference = cookies.get(
COOKIES_AGREEMENT_COOKIE_KEY,
) as CookiePreference
expect(cookiePreference).toBeDefined()
expect(cookiePreference.analyticsAllowed).toBe(false)
expect(cookiePreference.functionalAllowed).toBe(false)
})
Expand All @@ -92,7 +91,11 @@ describe('CookiesNotification', () => {
})

it('does not display the alert when cookies have been accepted', () => {
localStorage.setItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY, 'true')
const cookiePrefence: CookiePreference = {
analyticsAllowed: true,
functionalAllowed: true,
}
cookies.set(COOKIES_AGREEMENT_COOKIE_KEY, cookiePrefence)
const { alert } = renderComponent()
expect(alert).not.toBeInTheDocument()
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import FullWidthAlert from '../FullWidthAlert'
import { Link, Typography } from '@mui/material'
import CookiePreferencesDialog from './CookiePreferencesDialog'
import {
COOKIES_AGREEMENT_LOCALSTORAGE_KEY,
COOKIES_AGREEMENT_COOKIE_KEY,
CookiePreference,
allowAll,
allowNone,
useCookiePreferences,
} from '../../utils/hooks/useCookiePreferences'
import { PRIVACY_POLICY_LINK } from '../../utils/SynapseConstants'
import UniversalCookies from 'universal-cookie'

const cookies = new UniversalCookies()

export const alertConfig = {
title: 'Our site uses cookies.',
Expand Down Expand Up @@ -37,7 +40,7 @@ const CookiesNotification = (props: CookieNotificationProps) => {
const [, setCookiePreferences] = useCookiePreferences()

const [notificationDismissed, setNotificationDismissed] = useState(
localStorage.getItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY) !== null,
!!cookies.get(COOKIES_AGREEMENT_COOKIE_KEY),
)

const [isCookiePrefsDialogVisible, setIsCookiePrefsDialogVisible] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useCallback } from 'react'
import { atom, useAtom } from 'jotai'
import UniversalCookies from 'universal-cookie'

const cookies = new UniversalCookies()

export type CookiePreference = {
functionalAllowed: boolean
Expand All @@ -16,21 +19,22 @@ export const allowNone: CookiePreference = {
}

export const getCurrentCookiePreferences = () => {
const prefs = localStorage.getItem(COOKIES_AGREEMENT_LOCALSTORAGE_KEY)
const prefs = cookies.get(COOKIES_AGREEMENT_COOKIE_KEY, {
doNotParse: true,
}) as string | undefined
let cookiePreference = allowNone
try {
if (prefs != null) {
if (prefs != undefined) {
cookiePreference = JSON.parse(prefs) as CookiePreference
}
} catch (err) {
console.error(
`Failed to parse CookiePreference from value, falling back to allow none. value=${prefs}`,
)
}

return cookiePreference
}
export const COOKIES_AGREEMENT_LOCALSTORAGE_KEY =
export const COOKIES_AGREEMENT_COOKIE_KEY =
'org.sagebionetworks.security.cookies.portal.preference'

const cookiePreferencesAtom = atom<CookiePreference>(
Expand All @@ -50,10 +54,15 @@ export const useCookiePreferences = (): [
localStorage.clear()
sessionStorage.clear()
}
localStorage.setItem(
COOKIES_AGREEMENT_LOCALSTORAGE_KEY,
JSON.stringify(prefs),
)

const current = new Date()
const nextYear = new Date()
nextYear.setFullYear(current.getFullYear() + 1)
cookies.set(COOKIES_AGREEMENT_COOKIE_KEY, prefs, {
path: '/',
expires: nextYear,
})

setCookiePreferencesAtomValue(prefs)
},
[setCookiePreferencesAtomValue],
Expand Down

0 comments on commit 8efffd5

Please sign in to comment.