From a62b348fd6248b2bcce33f5e7db345159df15d8b Mon Sep 17 00:00:00 2001 From: Cuong Vu Date: Wed, 12 Feb 2020 16:07:19 +0700 Subject: [PATCH] feat: #220 terms and conditions modal first time login dev portal (#241) * feat: #220 terms and condition modal when dev first login dev portal * feat: #220 update test badges * feat: #220 update terms and conditions ui * fix: #220 update badges --- .../elements/src/components/Modal/index.tsx | 24 ++--- packages/marketplace/src/actions/auth.ts | 3 + .../terms-and-conditions-modal.tsx.snap | 1 + .../ui/terms-and-conditions-modal.tsx | 13 ++- .../marketplace/src/constants/action-types.ts | 3 + .../src/core/private-route-wrapper.tsx | 22 ++++- .../src/reducers/__tests__/auth.ts | 12 +++ packages/marketplace/src/reducers/auth.ts | 9 ++ .../marketplace/src/sagas/__tests__/auth.ts | 97 ++++++++++++++++++- packages/marketplace/src/sagas/auth.ts | 45 ++++++++- .../src/selector/__tests__/auth.ts | 14 +++ packages/marketplace/src/selector/auth.ts | 5 + .../src/tests/badges/badge-branches.svg | 2 +- .../src/tests/badges/badge-functions.svg | 2 +- .../src/tests/badges/badge-lines.svg | 2 +- .../src/tests/badges/badge-statements.svg | 2 +- .../marketplace/src/utils/__tests__/cookie.ts | 7 +- packages/marketplace/src/utils/cookie.ts | 16 ++- 18 files changed, 248 insertions(+), 31 deletions(-) create mode 100644 packages/marketplace/src/selector/__tests__/auth.ts create mode 100644 packages/marketplace/src/selector/auth.ts diff --git a/packages/elements/src/components/Modal/index.tsx b/packages/elements/src/components/Modal/index.tsx index e472532080..1a71c34273 100644 --- a/packages/elements/src/components/Modal/index.tsx +++ b/packages/elements/src/components/Modal/index.tsx @@ -20,7 +20,7 @@ export interface ModalProps { export interface ModalHeaderProps { title: string - afterClose: () => void + afterClose?: () => void } export const ModalFooter: React.SFC<{ footerItems: React.ReactNode }> = ({ footerItems }) => ( @@ -34,15 +34,17 @@ export const ModalBody: React.SFC<{ body: React.ReactNode }> = ({ body }) => ( export const ModalHeader: React.SFC = ({ title, afterClose }) => (

{title}

-
) @@ -92,7 +94,7 @@ export const Modal: React.FunctionComponent = ({ ) : ( <> {HeaderComponent && } - {!HeaderComponent && afterClose && title && } + {!HeaderComponent && title && } {children && } {footerItems && } diff --git a/packages/marketplace/src/actions/auth.ts b/packages/marketplace/src/actions/auth.ts index a24183725b..4431cc2383 100644 --- a/packages/marketplace/src/actions/auth.ts +++ b/packages/marketplace/src/actions/auth.ts @@ -13,3 +13,6 @@ export const authClear = actionCreator(ActionTypes.AUTH_CLEAR) export const checkFirstTimeLogin = actionCreator(ActionTypes.CHECK_FIRST_TIME_LOGIN) export const toggleFirstLogin = actionCreator(ActionTypes.TOGGLE_FIRST_LOGIN) export const userAcceptTermAndCondition = actionCreator(ActionTypes.USER_ACCEPT_TERM_AND_CONDITION) +export const checkTermsAcceptedWithCookie = actionCreator(ActionTypes.CHECK_TERM_ACCEPTED_WITH_COOKIE) +export const setTermsAcceptedWithCookie = actionCreator(ActionTypes.SET_TERMS_ACCEPTED_WITH_COOKIE) +export const setTermsAcceptedState = actionCreator(ActionTypes.SET_TERMS_ACCEPTED_STATE) diff --git a/packages/marketplace/src/components/ui/__tests__/__snapshots__/terms-and-conditions-modal.tsx.snap b/packages/marketplace/src/components/ui/__tests__/__snapshots__/terms-and-conditions-modal.tsx.snap index 3e00b9eb0b..ab27173fc2 100644 --- a/packages/marketplace/src/components/ui/__tests__/__snapshots__/terms-and-conditions-modal.tsx.snap +++ b/packages/marketplace/src/components/ui/__tests__/__snapshots__/terms-and-conditions-modal.tsx.snap @@ -21,6 +21,7 @@ exports[`Menu should match a snapshot 1`] = ` } + tapOutsideToDissmiss={true} title="Terms and Conditions" visible={true} > diff --git a/packages/marketplace/src/components/ui/terms-and-conditions-modal.tsx b/packages/marketplace/src/components/ui/terms-and-conditions-modal.tsx index 0deb57380d..de35cddc0d 100644 --- a/packages/marketplace/src/components/ui/terms-and-conditions-modal.tsx +++ b/packages/marketplace/src/components/ui/terms-and-conditions-modal.tsx @@ -3,8 +3,9 @@ import { Button, Modal, ModalProps } from '@reapit/elements' export type TermsAndConditionsModalProps = { onAccept: () => void - onDecline: () => void + onDecline?: () => void text?: string + tapOutsideToDissmiss?: boolean } & Pick const placeholderText = ` @@ -23,17 +24,21 @@ export const TermsAndConditionsModal: React.FunctionComponent { return ( - + {onDecline && ( + + )} diff --git a/packages/marketplace/src/constants/action-types.ts b/packages/marketplace/src/constants/action-types.ts index 09da50186f..7f69eea7fb 100644 --- a/packages/marketplace/src/constants/action-types.ts +++ b/packages/marketplace/src/constants/action-types.ts @@ -26,6 +26,9 @@ const ActionTypes = { CHECK_FIRST_TIME_LOGIN: 'CHECK_FIRST_TIME_LOGIN', TOGGLE_FIRST_LOGIN: 'TOGGLE_FIRST_LOGIN', USER_ACCEPT_TERM_AND_CONDITION: 'USER_ACCEPT_TERM_AND_CONDITION', + CHECK_TERM_ACCEPTED_WITH_COOKIE: 'CHECK_TERM_ACCEPTED_WITH_COOKIE', + SET_TERMS_ACCEPTED_WITH_COOKIE: 'SET_TERMS_ACCEPTED_WITH_COOKIE', + SET_TERMS_ACCEPTED_STATE: 'SET_TERMS_ACCEPTED_STATE', // Error actions ERROR_THROWN_COMPONENT: 'ERROR_THROWN_COMPONENT', diff --git a/packages/marketplace/src/core/private-route-wrapper.tsx b/packages/marketplace/src/core/private-route-wrapper.tsx index fcf438b0af..30edd6e254 100644 --- a/packages/marketplace/src/core/private-route-wrapper.tsx +++ b/packages/marketplace/src/core/private-route-wrapper.tsx @@ -3,24 +3,28 @@ import { RouteComponentProps } from 'react-router-dom' import { connect } from 'react-redux' import { ReduxState } from 'src/types/core' import Menu from '@/components/ui/menu' +import TermsAndConditionsModal from '@/components/ui/terms-and-conditions-modal' import { Loader, Section, FlexContainerBasic, AppNavContainer } from '@reapit/elements' import { LoginType, RefreshParams, getTokenFromQueryString, redirectToOAuth } from '@reapit/cognito-auth' import { Dispatch } from 'redux' import { withRouter, Redirect } from 'react-router' -import { authSetRefreshSession } from '../actions/auth' import { getDefaultRouteByLoginType, getDefaultPathByLoginType } from '@/utils/auth-route' +import { authSetRefreshSession, checkTermsAcceptedWithCookie, setTermsAcceptedWithCookie } from '../actions/auth' import { getCookieString, COOKIE_FIRST_TIME_LOGIN } from '@/utils/cookie' const { Suspense } = React export interface PrivateRouteWrapperConnectActions { setRefreshSession: (refreshParams: RefreshParams) => void + checkTermsAcceptedWithCookie: () => void + setTermsAcceptedWithCookie: () => void } export interface PrivateRouteWrapperConnectState { hasSession: boolean isDesktopMode: boolean loginType: LoginType + isTermAccepted: boolean } export type PrivateRouteWrapperProps = PrivateRouteWrapperConnectState & @@ -35,11 +39,17 @@ export const PrivateRouteWrapper: React.FunctionComponent { + React.useEffect(checkTermsAcceptedWithCookie, []) + const params = new URLSearchParams(location.search) const state = params.get('state') const type = state && state.includes('ADMIN') ? 'ADMIN' : state && state.includes('DEVELOPER') ? 'DEVELOPER' : loginType + const firstLoginCookie = getCookieString(COOKIE_FIRST_TIME_LOGIN) const route = getDefaultRouteByLoginType(type, firstLoginCookie) const cognitoClientId = process.env.COGNITO_CLIENT_ID_MARKETPLACE as string @@ -64,6 +74,11 @@ export const PrivateRouteWrapper: React.FunctionComponent + hasSession: !!state.auth.loginSession || !!state.auth.refreshSession, loginType: state.auth.loginType, isDesktopMode: state?.auth?.refreshSession?.mode === 'DESKTOP', + isTermAccepted: state.auth.isTermAccepted, }) const mapDispatchToProps = (dispatch: Dispatch): PrivateRouteWrapperConnectActions => ({ setRefreshSession: refreshParams => dispatch(authSetRefreshSession(refreshParams)), + checkTermsAcceptedWithCookie: () => { + dispatch(checkTermsAcceptedWithCookie()) + }, + setTermsAcceptedWithCookie: () => dispatch(setTermsAcceptedWithCookie(true)), }) export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PrivateRouteWrapper)) diff --git a/packages/marketplace/src/reducers/__tests__/auth.ts b/packages/marketplace/src/reducers/__tests__/auth.ts index 9222b4b506..6f06427082 100644 --- a/packages/marketplace/src/reducers/__tests__/auth.ts +++ b/packages/marketplace/src/reducers/__tests__/auth.ts @@ -68,4 +68,16 @@ describe('auth reducer', () => { const newState = authReducer(undefined, { type: ActionTypes.TOGGLE_FIRST_LOGIN as ActionType, data }) expect(newState.firstLogin).toEqual(data) }) + + it('should set isTermAccepted state when SET_TERMS_ACCEPTED_STATE is called ', () => { + const newState = authReducer(undefined, { + type: ActionTypes.SET_TERMS_ACCEPTED_STATE as ActionType, + data: true, + }) + const expected = { + ...defaultState(), + isTermAccepted: true, + } + expect(newState).toEqual(expected) + }) }) diff --git a/packages/marketplace/src/reducers/auth.ts b/packages/marketplace/src/reducers/auth.ts index 6e9b71b11e..74625e0b93 100644 --- a/packages/marketplace/src/reducers/auth.ts +++ b/packages/marketplace/src/reducers/auth.ts @@ -8,6 +8,7 @@ import { authSetRefreshSession, authChangeLoginType, toggleFirstLogin, + setTermsAcceptedState, } from '../actions/auth' import { LoginSession, RefreshParams, LoginType, getSessionCookie } from '@reapit/cognito-auth' import { COOKIE_SESSION_KEY_MARKETPLACE } from '../constants/api' @@ -18,6 +19,7 @@ export interface AuthState { loginType: LoginType loginSession: LoginSession | null refreshSession: RefreshParams | null + isTermAccepted: boolean } export const defaultState = (): AuthState => { @@ -26,6 +28,7 @@ export const defaultState = (): AuthState => { error: false, loginSession: null, firstLogin: false, + isTermAccepted: true, loginType: refreshSession ? refreshSession.loginType : 'CLIENT', refreshSession, } @@ -83,6 +86,12 @@ const authReducer = (state: AuthState = defaultState(), action: Action): Au } } + if (isType(action, setTermsAcceptedState)) { + return { + ...state, + isTermAccepted: action.data, + } + } return state } diff --git a/packages/marketplace/src/sagas/__tests__/auth.ts b/packages/marketplace/src/sagas/__tests__/auth.ts index 4b45dd781e..e9b1259ae9 100644 --- a/packages/marketplace/src/sagas/__tests__/auth.ts +++ b/packages/marketplace/src/sagas/__tests__/auth.ts @@ -1,9 +1,15 @@ import MockDate from 'mockdate' -import { put, all, takeLatest, call, fork } from '@redux-saga/core/effects' +import { select, put, all, takeLatest, call, fork } from '@redux-saga/core/effects' import { setUserSession, removeSession, LoginParams, LoginSession, redirectToLogout } from '@reapit/cognito-auth' import { Action } from '@/types/core' import { cloneableGenerator } from '@redux-saga/testing-utils' -import { getCookieString, setCookieString, COOKIE_FIRST_TIME_LOGIN } from '@/utils/cookie' +import { + getCookieString, + setCookieString, + COOKIE_FIRST_TIME_LOGIN, + COOKIE_TERMS_ACCEPTED, + COOKIE_MAX_AGE_INFINITY, +} from '@/utils/cookie' import authSagas, { doLogin, doLogout, @@ -15,12 +21,23 @@ import authSagas, { setFirstTimeLogin, checkFirstTimeLoginListen, checkFirstTimeLogin, + setTermsAcceptedWithCookieHelper, + checkTermsAcceptedWithCookieHelper, + checkTermsAcceptedListen, + setTermsAcceptedListen, } from '../auth' import ActionTypes from '../../constants/action-types' -import { authLoginSuccess, authLogoutSuccess, authLoginFailure, toggleFirstLogin } from '../../actions/auth' +import { + authLoginSuccess, + authLogoutSuccess, + authLoginFailure, + toggleFirstLogin, + setTermsAcceptedState, +} from '../../actions/auth' import Routes from '../../constants/routes' import { ActionType } from '../../types/core' import { COOKIE_SESSION_KEY_MARKETPLACE } from '../../constants/api' +import { selectLoginType } from '@/selector/auth' jest.mock('../../utils/session') jest.mock('../../core/router', () => ({ @@ -31,6 +48,25 @@ jest.mock('../../core/router', () => ({ jest.mock('../../core/store') jest.mock('@reapit/cognito-auth') +/* mock to make new Date() a consistent value */ +const RealDate = Date + +function mockDate() { + global.Date = class extends RealDate { + constructor() { + super() + return new RealDate('2017-06-13T04:41:20') as Date + } + } as any +} + +beforeEach(() => { + mockDate() +}) +afterEach(() => { + global.Date = RealDate +}) + export const mockLoginSession = { userName: 'bob@acme.com', accessTokenExpiry: 2, @@ -143,6 +179,8 @@ describe('auth thunks', () => { fork(clearAuthListen), fork(checkFirstTimeLoginListen), fork(setFirstLoginListen), + fork(checkTermsAcceptedListen), + fork(setTermsAcceptedListen), ]), ) expect(gen.next().done).toBe(true) @@ -178,4 +216,57 @@ describe('auth thunks', () => { expect(gen.next().done).toBe(true) }) }) + + describe('checkTermsAcceptedWithCookie', () => { + it('should run correctly with developer login type', () => { + const gen = cloneableGenerator(checkTermsAcceptedWithCookieHelper)() + expect(gen.next().value).toEqual(select(selectLoginType)) + expect(gen.next('DEVELOPER').value).toEqual(call(getCookieString, COOKIE_TERMS_ACCEPTED)) + expect(gen.next('2019-12-18T16:30:00').value).toEqual(put(setTermsAcceptedState(true))) + expect(gen.next().done).toBe(true) + }) + + it('should run correctly with other login type', () => { + const gen = cloneableGenerator(checkTermsAcceptedWithCookieHelper)() + expect(gen.next().value).toEqual(select(selectLoginType)) + expect(gen.next('CLIENT').done).toBe(true) + }) + }) + + describe('setTermsAcceptedWithCookieHelper', () => { + it('should run correctly with true', () => { + const gen = cloneableGenerator(setTermsAcceptedWithCookieHelper)({ data: true }) + expect(gen.next().value).toEqual( + call(setCookieString, COOKIE_TERMS_ACCEPTED, new Date(), COOKIE_MAX_AGE_INFINITY), + ) + expect(gen.next().value).toEqual(put(setTermsAcceptedState(true))) + expect(gen.next().done).toBe(true) + }) + + it('should run correctly with false', () => { + const gen = cloneableGenerator(setTermsAcceptedWithCookieHelper)({ data: false }) + expect(gen.next().value).toEqual(put(setTermsAcceptedState(false))) + expect(gen.next().done).toBe(true) + }) + }) + + describe('checkTermsAcceptedListen', () => { + it('should run correctly', () => { + const gen = checkTermsAcceptedListen() + expect(gen.next().value).toEqual( + takeLatest(ActionTypes.CHECK_TERM_ACCEPTED_WITH_COOKIE, checkTermsAcceptedWithCookieHelper), + ) + expect(gen.next().done).toBe(true) + }) + }) + + describe('setTermsAcceptedListen', () => { + it('should run correctly', () => { + const gen = setTermsAcceptedListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.SET_TERMS_ACCEPTED_WITH_COOKIE, setTermsAcceptedWithCookieHelper), + ) + expect(gen.next().done).toBe(true) + }) + }) }) diff --git a/packages/marketplace/src/sagas/auth.ts b/packages/marketplace/src/sagas/auth.ts index 5fc72b6823..17aaad6405 100644 --- a/packages/marketplace/src/sagas/auth.ts +++ b/packages/marketplace/src/sagas/auth.ts @@ -1,12 +1,25 @@ -import { takeLatest, put, call, all, fork } from '@redux-saga/core/effects' +import { takeLatest, put, call, all, fork, select } from '@redux-saga/core/effects' import ActionTypes from '../constants/action-types' -import { authLoginSuccess, authLoginFailure, authLogoutSuccess, toggleFirstLogin } from '../actions/auth' +import { + authLoginSuccess, + authLoginFailure, + authLogoutSuccess, + toggleFirstLogin, + setTermsAcceptedState, +} from '../actions/auth' import { Action } from '@/types/core.ts' import { LoginSession, LoginParams, setUserSession, removeSession, redirectToLogout } from '@reapit/cognito-auth' import store from '../core/store' import { getAuthRouteByLoginType } from '@/utils/auth-route' -import { getCookieString, setCookieString, COOKIE_FIRST_TIME_LOGIN } from '@/utils/cookie' +import { + getCookieString, + setCookieString, + COOKIE_FIRST_TIME_LOGIN, + COOKIE_TERMS_ACCEPTED, + COOKIE_MAX_AGE_INFINITY, +} from '@/utils/cookie' import { COOKIE_SESSION_KEY_MARKETPLACE } from '../constants/api' +import { selectLoginType } from '@/selector/auth' import { logger } from 'logger' export const doLogin = function*({ data }: Action) { @@ -61,6 +74,22 @@ export const setFirstTimeLogin = function*() { yield put(toggleFirstLogin(false)) } +export const checkTermsAcceptedWithCookieHelper = function*() { + const loginType = yield select(selectLoginType) + // for now only check when login as developer + if (loginType === 'DEVELOPER') { + const isTermAccepted = yield call(getCookieString, COOKIE_TERMS_ACCEPTED) + yield put(setTermsAcceptedState(!!isTermAccepted)) + } +} + +export const setTermsAcceptedWithCookieHelper = function*({ data: isAccepted }) { + if (isAccepted) { + yield call(setCookieString, COOKIE_TERMS_ACCEPTED, new Date(), COOKIE_MAX_AGE_INFINITY) + } + yield put(setTermsAcceptedState(isAccepted)) +} + export const loginListen = function*() { yield takeLatest(ActionTypes.AUTH_LOGIN, doLogin) } @@ -81,6 +110,14 @@ export const setFirstLoginListen = function*() { yield takeLatest(ActionTypes.USER_ACCEPT_TERM_AND_CONDITION, setFirstTimeLogin) } +export const checkTermsAcceptedListen = function*() { + yield takeLatest(ActionTypes.CHECK_TERM_ACCEPTED_WITH_COOKIE, checkTermsAcceptedWithCookieHelper) +} + +export const setTermsAcceptedListen = function*() { + yield takeLatest>(ActionTypes.SET_TERMS_ACCEPTED_WITH_COOKIE, setTermsAcceptedWithCookieHelper) +} + const authSaga = function*() { yield all([ fork(loginListen), @@ -88,6 +125,8 @@ const authSaga = function*() { fork(clearAuthListen), fork(checkFirstTimeLoginListen), fork(setFirstLoginListen), + fork(checkTermsAcceptedListen), + fork(setTermsAcceptedListen), ]) } diff --git a/packages/marketplace/src/selector/__tests__/auth.ts b/packages/marketplace/src/selector/__tests__/auth.ts new file mode 100644 index 0000000000..6161491137 --- /dev/null +++ b/packages/marketplace/src/selector/__tests__/auth.ts @@ -0,0 +1,14 @@ +import { ReduxState } from '@/types/core' +import { selectLoginType } from '../auth' + +describe('selectLoginType', () => { + it('should run correctly', () => { + const mockState = { + auth: { + loginType: 'CLIENT', + }, + } as ReduxState + const result = selectLoginType(mockState) + expect(result).toEqual(mockState.auth.loginType) + }) +}) diff --git a/packages/marketplace/src/selector/auth.ts b/packages/marketplace/src/selector/auth.ts new file mode 100644 index 0000000000..b81b0bfb2c --- /dev/null +++ b/packages/marketplace/src/selector/auth.ts @@ -0,0 +1,5 @@ +import { ReduxState } from '@/types/core' + +export const selectLoginType = (state: ReduxState) => { + return state.auth.loginType +} diff --git a/packages/marketplace/src/tests/badges/badge-branches.svg b/packages/marketplace/src/tests/badges/badge-branches.svg index 1a2614029a..92389eece2 100644 --- a/packages/marketplace/src/tests/badges/badge-branches.svg +++ b/packages/marketplace/src/tests/badges/badge-branches.svg @@ -1 +1 @@ - Coverage:branchesCoverage:branches69.64%69.64% \ No newline at end of file + Coverage:branchesCoverage:branches70.47%70.47% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-functions.svg b/packages/marketplace/src/tests/badges/badge-functions.svg index 286862ebe4..ca52f6afcf 100644 --- a/packages/marketplace/src/tests/badges/badge-functions.svg +++ b/packages/marketplace/src/tests/badges/badge-functions.svg @@ -1 +1 @@ - Coverage:functionsCoverage:functions73.66%73.66% \ No newline at end of file + Coverage:functionsCoverage:functions73.71%73.71% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-lines.svg b/packages/marketplace/src/tests/badges/badge-lines.svg index 17dfe8d459..bafd909e37 100644 --- a/packages/marketplace/src/tests/badges/badge-lines.svg +++ b/packages/marketplace/src/tests/badges/badge-lines.svg @@ -1 +1 @@ - Coverage:linesCoverage:lines90.3%90.3% \ No newline at end of file + Coverage:linesCoverage:lines90.37%90.37% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-statements.svg b/packages/marketplace/src/tests/badges/badge-statements.svg index 9981e86ffb..7e1340271b 100644 --- a/packages/marketplace/src/tests/badges/badge-statements.svg +++ b/packages/marketplace/src/tests/badges/badge-statements.svg @@ -1 +1 @@ - Coverage:statementsCoverage:statements89.46%89.46% \ No newline at end of file + Coverage:statementsCoverage:statements89.53%89.53% \ No newline at end of file diff --git a/packages/marketplace/src/utils/__tests__/cookie.ts b/packages/marketplace/src/utils/__tests__/cookie.ts index d3300f1aae..0533ccea70 100644 --- a/packages/marketplace/src/utils/__tests__/cookie.ts +++ b/packages/marketplace/src/utils/__tests__/cookie.ts @@ -18,18 +18,19 @@ describe('cookie utils', () => { const validHost = 'https://something.reapit.cloud' hardtack.set = jest.fn() const now = new Date() - setCookieString(COOKIE_FIRST_TIME_LOGIN, now, validHost) - expect(hardtack.set).toHaveBeenCalledWith(COOKIE_FIRST_TIME_LOGIN, now, { + setCookieString(COOKIE_FIRST_TIME_LOGIN, now, 10, validHost) + expect(hardtack.set).toHaveBeenCalledWith(COOKIE_FIRST_TIME_LOGIN, now.toString(), { path: '/', domain: '.reapit.cloud', samesite: 'lax', + maxAge: 10, }) }) it('should not set a cookie if host is not in the whitelist array', () => { const inValidHost = 'https://something.com' hardtack.set = jest.fn() const now = new Date() - setCookieString(COOKIE_FIRST_TIME_LOGIN, now, inValidHost) + setCookieString(COOKIE_FIRST_TIME_LOGIN, now, 10, inValidHost) expect(hardtack.set).not.toHaveBeenCalled() }) }) diff --git a/packages/marketplace/src/utils/cookie.ts b/packages/marketplace/src/utils/cookie.ts index 745f40567b..63103e7b3c 100644 --- a/packages/marketplace/src/utils/cookie.ts +++ b/packages/marketplace/src/utils/cookie.ts @@ -1,6 +1,12 @@ import hardtack from 'hardtack' +// cookie 10 years +export const COOKIE_MAX_AGE_INFINITY = 60 * 60 * 24 * 365 * 10 export const COOKIE_FIRST_TIME_LOGIN = 'reapit-first-login-complete' + +export const COOKIE_FIRST_TIME_LOGIN_DEVELOPER = 'reapit-developer-first-login-complete' +export const COOKIE_TERMS_ACCEPTED = 'reapit-term-accepted' + export const COOKIE_DOMAIN_WHITELIST = ['.reapit.cloud', 'localhost'] export const getCookieString = (key: string): string => { @@ -12,14 +18,20 @@ export const getCookieString = (key: string): string => { } } -export const setCookieString = (key, value, href = window.location.href): void => { +export const setCookieString = ( + key: string, + value: string | Date, + maxAge?: number, + href: string = window.location.href, +): void => { const whitelistedHost = COOKIE_DOMAIN_WHITELIST.filter(item => href.includes(item))[0] if (whitelistedHost) { - hardtack.set(key, value, { + hardtack.set(key, value.toString(), { path: '/', domain: whitelistedHost, samesite: 'lax', + maxAge, }) } }