Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref: Update TOS to work for service less users. #2321

Merged
merged 13 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
const PullRequestPage = lazy(() => import('./pages/PullRequestPage'))
const RepoPage = lazy(() => import('./pages/RepoPage'))
const SyncProviderPage = lazy(() => import('./pages/SyncProviderPage'))
const TermsOfService = lazy(() => import('pages/TermsOfService'))

Check warning on line 28 in src/App.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/App.jsx#L28

Added line #L28 was not covered by tests

Check warning on line 28 in src/App.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/App.jsx#L28

Added line #L28 was not covered by tests

Check warning on line 28 in src/App.jsx

View check run for this annotation

Codecov / codecov/patch

src/App.jsx#L28

Added line #L28 was not covered by tests

const HomePageRedirect = () => {
const { provider } = useParams()
Expand Down Expand Up @@ -60,6 +61,11 @@
<SyncProviderPage />
</BaseLayout>
</SentryRoute>
<SentryRoute path="/terms" exact>
<BaseLayout>
<TermsOfService />
</BaseLayout>
</SentryRoute>
{config.IS_SELF_HOSTED && (
<SentryRoute path="/admin/:provider">
<BaseLayout>
Expand Down
10 changes: 10 additions & 0 deletions src/App.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,16 @@ describe('App', () => {
},
},
],
[
{
testLabel: 'TOSPage',
pathname: '/terms',
expected: {
page: /TermsOfService/i,
location: '/terms',
},
},
],
]

describe.each(cloudFullRouterCases)(
Expand Down
7 changes: 1 addition & 6 deletions src/layouts/BaseLayout/BaseLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
const LimitedHeader = lazy(() => import('layouts/LimitedHeader'))
const DefaultOrgSelector = lazy(() => import('pages/DefaultOrgSelector'))
const InstallationHelpBanner = lazy(() => import('./InstallationHelpBanner'))
const TermsOfService = lazy(() => import('pages/TermsOfService'))

const FullPageLoader = () => (
<div className="mt-16 flex flex-1 items-center justify-center">
Expand All @@ -36,11 +35,7 @@
const { isImpersonating } = useImpersonate()

if (showAgreeToTerms && !isFullExperience) {
return (
<Suspense fallback={null}>
<TermsOfService />
</Suspense>
)
return <Redirect to="/terms" />

Check warning on line 38 in src/layouts/BaseLayout/BaseLayout.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/layouts/BaseLayout/BaseLayout.jsx#L38

Added line #L38 was not covered by tests

Check warning on line 38 in src/layouts/BaseLayout/BaseLayout.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/layouts/BaseLayout/BaseLayout.jsx#L38

Added line #L38 was not covered by tests

Check warning on line 38 in src/layouts/BaseLayout/BaseLayout.jsx

View check run for this annotation

Codecov / codecov/patch

src/layouts/BaseLayout/BaseLayout.jsx#L38

Added line #L38 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a dedicated route and using redirects means the original path the user was trying to access will be lost. Example:

User comes from a PR link, hasn't signed TOS, when they sign it they're sent to the /:provider/:org not the PR they clicked on.

https://github.com/codecov/gazebo/pull/2321/files#diff-a8fba335305fed7cd0a638ac77db50888a5c94a8c0115d5cd78a00664904dec2R112

Is this a known trade off we're making?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it’s fine. we require no synced services to render this page, TOS lived under a component that used queries that serve on providers so it made sense to take it out, otherwise we would have to alter HomePageRedirect
and other components to make this happen

Copy link
Contributor Author

@RulaKhaled RulaKhaled Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ps. Might be worth it to do the same thing for default org? sync page has it’s own dedicated route as well, I think it’s weird to jump from /terms -> /sync -> /gh But then again, default org works fine with services.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've to raised this to AJ. I (unfortunately) think loosing the navigation path is not good UX and that another approach might be needed here.. But I'll let him weigh the trade offs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. do you mind including me in the conversation please?

Copy link
Contributor

@terry-codecov terry-codecov Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup for sure! I directed him to this PR actually how ever if more slacking happens we'll move to the team channel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

synced w/AJ i'll try to get it working without a new route, thought it does not effect new users but AJ believe it's good to handle too

}

if (redirectToSyncPage && !isFullExperience) {
Expand Down
42 changes: 17 additions & 25 deletions src/layouts/BaseLayout/BaseLayout.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ jest.mock('services/impersonate')
jest.mock('shared/featureFlags')
jest.mock('shared/GlobalTopBanners', () => () => 'GlobalTopBanners')
jest.mock('./InstallationHelpBanner', () => () => 'InstallationHelpBanner')
jest.mock('pages/TermsOfService', () => () => 'TermsOfService')
jest.mock('pages/DefaultOrgSelector', () => () => 'DefaultOrgSelector')

const mockOwner = {
Expand Down Expand Up @@ -167,9 +166,6 @@ describe('BaseLayout', () => {
graphql.query('Seats', (_, res, ctx) =>
res(ctx.status(200), ctx.data({}))
),
graphql.query('TermsOfService', (_, res, ctx) =>
res(ctx.status(200), ctx.data({}))
),
graphql.query('UseMyOrganizations', (_, res, ctx) =>
res(
ctx.status(200),
Expand Down Expand Up @@ -218,9 +214,6 @@ describe('BaseLayout', () => {

const defaultOrg = screen.queryByText(/DefaultOrgSelector/)
expect(defaultOrg).not.toBeInTheDocument()

const termsOfService = screen.queryByText(/TermsOfService/)
expect(termsOfService).not.toBeInTheDocument()
})
})

Expand All @@ -239,9 +232,6 @@ describe('BaseLayout', () => {

const defaultOrg = screen.queryByText(/DefaultOrgSelector/)
expect(defaultOrg).not.toBeInTheDocument()

const termsOfService = screen.queryByText(/TermsOfService/)
expect(termsOfService).not.toBeInTheDocument()
})
})

Expand All @@ -261,22 +251,7 @@ describe('BaseLayout', () => {

const defaultOrg = screen.queryByText(/DefaultOrgSelector/)
expect(defaultOrg).not.toBeInTheDocument()

const termsOfService = screen.queryByText(/TermsOfService/)
expect(termsOfService).not.toBeInTheDocument()
})
})

it(`renders the ${expectedPage}`, async () => {
setup({ termsOfServicePage: true, currentUser: loggedInUser })

render(<BaseLayout>hello</BaseLayout>, {
wrapper: wrapper(),
})

expect(await screen.findByText(expectedMatcher)).toBeTruthy()
const tos = screen.getByText(expectedMatcher)
expect(tos).toBeInTheDocument()
})
})

Expand Down Expand Up @@ -308,6 +283,23 @@ describe('BaseLayout', () => {
})
})

describe('user has not accepted terms of service', () => {
it('redirects the user to /terms', async () => {
setup({
termsOfServicePage: true,
internalUser: {
termsAgreement: false,
},
})

render(<BaseLayout>hello</BaseLayout>, {
wrapper: wrapper(),
})

await waitFor(() => expect(testLocation.pathname).toBe('/terms'))
})
})

describe('user has not synced with providers', () => {
it('redirects the user to /sync', async () => {
setup({
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/BaseLayout/hooks/useUserAccessGate.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
!isGuest &&
!config.IS_SELF_HOSTED
) {
showAgreeToTerms = userData?.termsAgreement === false
showAgreeToTerms = internalUser?.termsAgreement === false

Check warning on line 82 in src/layouts/BaseLayout/hooks/useUserAccessGate.js

View check run for this annotation

Codecov Public QA / codecov/patch

src/layouts/BaseLayout/hooks/useUserAccessGate.js#L82

Added line #L82 was not covered by tests

Check warning on line 82 in src/layouts/BaseLayout/hooks/useUserAccessGate.js

View check run for this annotation

Codecov - QA / codecov/patch

src/layouts/BaseLayout/hooks/useUserAccessGate.js#L82

Added line #L82 was not covered by tests

Check warning on line 82 in src/layouts/BaseLayout/hooks/useUserAccessGate.js

View check run for this annotation

Codecov / codecov/patch

src/layouts/BaseLayout/hooks/useUserAccessGate.js#L82

Added line #L82 was not covered by tests
}

const onSyncPage = currentRoute.path === '/sync'
Expand Down
28 changes: 26 additions & 2 deletions src/layouts/BaseLayout/hooks/useUserAccessGate.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,30 @@ const internalUserHasSyncedProviders = {
],
}

const internalUserWithSignedTOS = {
email: userSignedInIdentity.email,
name: userSignedInIdentity.name,
externalId: '123',
owners: [
{
service: 'github',
},
],
termsAgreement: true,
}

const internalUserWithUnsignedTOS = {
email: userSignedInIdentity.email,
name: userSignedInIdentity.name,
externalId: '123',
owners: [
{
service: 'github',
},
],
termsAgreement: false,
}

type InternalUser =
| typeof internalUserNoSyncedProviders
| typeof internalUserHasSyncedProviders
Expand Down Expand Up @@ -249,7 +273,7 @@ describe('useUserAccessGate', () => {
'signed TOS',
{
user: loggedInUser,
internalUser: internalUserHasSyncedProviders,
internalUser: internalUserWithSignedTOS,
termsOfServicePage: true,
isSelfHosted: false,
defaultOrgSelectorPage: false,
Expand Down Expand Up @@ -361,7 +385,7 @@ describe('useUserAccessGate', () => {
'unsigned TOS',
{
user: loggedInUnsignedUser,
internalUser: internalUserHasSyncedProviders,
internalUser: internalUserWithUnsignedTOS,
termsOfServicePage: true,
isSelfHosted: false,
defaultOrgSelectorPage: false,
Expand Down
34 changes: 28 additions & 6 deletions src/pages/TermsOfService/TermsOfService.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { zodResolver } from '@hookform/resolvers/zod'
import gt from 'lodash/gt'
import PropType from 'prop-types'
import { useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { Redirect } from 'react-router-dom'
import { z } from 'zod'

import umbrellaSvg from 'assets/svg/umbrella.svg'
import { useUser } from 'services/user'
import { useInternalUser } from 'services/user'
import { useFlags } from 'shared/featureFlags'
import { loginProviderToShortName } from 'shared/utils/loginProviders'
import A from 'ui/A'
import Button from 'ui/Button'
import TextInput from 'ui/TextInput'
Expand All @@ -18,8 +22,8 @@
tos: z.literal(true),
})

function isDisabled({ isValid, isDirty }) {
return (!isValid && isDirty) || !isDirty
function isDisabled({ isValid, isDirty, isMutationLoading }) {

Check warning on line 25 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L25

Added line #L25 was not covered by tests

Check warning on line 25 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L25

Added line #L25 was not covered by tests

Check warning on line 25 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L25

Added line #L25 was not covered by tests
return (!isValid && isDirty) || !isDirty || isMutationLoading
}

function EmailInput({ register, marketingEmailMessage, showEmailRequired }) {
Expand Down Expand Up @@ -61,7 +65,7 @@
resolver: zodResolver(FormSchema),
mode: 'onChange',
})
const { mutate } = useSaveTermsAgreement({
const { mutate, isLoading: isMutationLoading } = useSaveTermsAgreement({

Check warning on line 68 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L68

Added line #L68 was not covered by tests

Check warning on line 68 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L68

Added line #L68 was not covered by tests

Check warning on line 68 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L68

Added line #L68 was not covered by tests
onSuccess: ({ data }) => {
if (data?.saveTermsAgreement?.error) {
setError('apiError', data?.saveTermsAgreement?.error)
Expand All @@ -70,12 +74,18 @@
},
onError: (error) => setError('apiError', error),
})
const { data: currentUser, isLoading: userIsLoading } = useUser()
const { data: currentUser, isLoading: userIsLoading } = useInternalUser()
const hasSynced = gt(currentUser?.owners?.length, 0)

Check warning on line 78 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L77-L78

Added lines #L77 - L78 were not covered by tests

Check warning on line 78 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L77-L78

Added lines #L77 - L78 were not covered by tests

Check warning on line 78 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L77-L78

Added lines #L77 - L78 were not covered by tests

const { termsOfServicePage } = useFlags({

Check warning on line 80 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L80

Added line #L80 was not covered by tests

Check warning on line 80 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L80

Added line #L80 was not covered by tests

Check warning on line 80 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L80

Added line #L80 was not covered by tests
termsOfServicePage: false,
})

const onSubmit = (data) => {
mutate({
businessEmail: data?.marketingEmail || currentUser?.email,
termsAgreement: true,
marketingConsent: data?.marketingConsent,
})
}

Expand All @@ -93,6 +103,18 @@

if (userIsLoading) return null

if (!termsOfServicePage || currentUser?.termsAgreement) {
if (hasSynced) {
const service = currentUser?.owners?.[0]?.service
const owner = currentUser?.owners?.[0]?.username

Check warning on line 109 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L108-L109

Added lines #L108 - L109 were not covered by tests

Check warning on line 109 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L108-L109

Added lines #L108 - L109 were not covered by tests

Check warning on line 109 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L108-L109

Added lines #L108 - L109 were not covered by tests
if (service) {
const provider = loginProviderToShortName(service)
return <Redirect to={`/${provider}/${owner}`} />

Check warning on line 112 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L111-L112

Added lines #L111 - L112 were not covered by tests

Check warning on line 112 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L111-L112

Added lines #L111 - L112 were not covered by tests

Check warning on line 112 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L111-L112

Added lines #L111 - L112 were not covered by tests
}
}
return <Redirect to="/sync" />

Check warning on line 115 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov Public QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L115

Added line #L115 was not covered by tests

Check warning on line 115 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L115

Added line #L115 was not covered by tests

Check warning on line 115 in src/pages/TermsOfService/TermsOfService.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/TermsOfService/TermsOfService.jsx#L115

Added line #L115 was not covered by tests
}

return (
<div className="mx-auto w-full max-w-[38rem] text-sm text-ds-gray-octonary">
<div className="mt-14 flex gap-2">
Expand Down Expand Up @@ -177,7 +199,7 @@
)}
<div className="mt-3 flex justify-end">
<Button
disabled={isDisabled(formState)}
disabled={isDisabled(formState, isMutationLoading)}
type="submit"
hook="user signed tos"
>
Expand Down
Loading
Loading