Skip to content

Commit

Permalink
chore(payments): remove payment flags checks from payment controller (#…
Browse files Browse the repository at this point in the history
…7354)

* remove payment flags checks from payment controller

* remove payment flags on fieldlistdrawer

* remove payment flags on settings page
  • Loading branch information
KenLSM authored Jun 3, 2024
1 parent 9496aec commit 1e66a8a
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import {
Text,
} from '@chakra-ui/react'

import { featureFlags } from '~shared/constants'

import { Tab } from '~components/Tabs'

import { useCreatePageSidebar } from '~features/admin-form/create/common/CreatePageSidebarContext'
import { useFeatureFlags } from '~features/feature-flags/queries'
import { useUser } from '~features/user/queries'

import { useCreateTabForm } from '../../../builder-and-design/useCreateTabForm'
import { CreatePageDrawerCloseButton } from '../../../common'
Expand All @@ -31,12 +27,6 @@ export const FieldListDrawer = (): JSX.Element => {
const { fieldListTabIndex, setFieldListTabIndex } = useCreatePageSidebar()
const { isLoading } = useCreateTabForm()

const { user } = useUser()
const { data: flags } = useFeatureFlags()

const displayPayments =
user?.betaFlags?.payment || flags?.has(featureFlags.payment)

const tabsDataList = [
{
header: 'Basic',
Expand All @@ -55,7 +45,7 @@ export const FieldListDrawer = (): JSX.Element => {
{
header: 'Payments',
component: PaymentsInputPanel,
isHidden: !displayPayments,
isHidden: false,
isDisabled: isLoading,
key: FieldListTabIndex.Payments,
},
Expand Down
41 changes: 11 additions & 30 deletions frontend/src/features/admin-form/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,9 @@ import {
Tabs,
} from '@chakra-ui/react'

import { featureFlags } from '~shared/constants'

import { ADMINFORM_RESULTS_SUBROUTE, ADMINFORM_ROUTE } from '~constants/routes'
import { useDraggable } from '~hooks/useDraggable'

import { useFeatureFlags } from '~features/feature-flags/queries'
import { useUser } from '~features/user/queries'

import { useAdminFormCollaborators } from '../common/queries'

import { SettingsTab } from './components/SettingsTab'
Expand All @@ -28,12 +23,16 @@ import { SettingsPaymentsPage } from './SettingsPaymentsPage'
import { SettingsTwilioPage } from './SettingsTwilioPage'
import { SettingsWebhooksPage } from './SettingsWebhooksPage'

const settingsTabsOrder = ['general', 'singpass', 'twilio', 'webhooks']
const settingsTabsOrder = [
'general',
'singpass',
'twilio',
'webhooks',
'payments',
]

export const SettingsPage = (): JSX.Element => {
const { formId, settingsTab } = useParams()
const { user } = useUser()
const { data: flags } = useFeatureFlags()

if (!formId) throw new Error('No formId provided')

Expand All @@ -49,24 +48,10 @@ export const SettingsPage = (): JSX.Element => {

const { ref, onMouseDown } = useDraggable<HTMLDivElement>()

const displayPayments =
user?.betaFlags?.payment || flags?.has(featureFlags.payment)

const [tabIndex, setTabIndex] = useState(
settingsTabsOrder.indexOf(settingsTab ?? ''),
)

// Note: Admins are not redirected to /general on invalid settings tabs as we
// don't want to do this prematurely before displayPayments can be determined.
useEffect(() => {
if (displayPayments) {
// Dynamically push payments tab to settings tab order as needed, in case
// there may be multiple hidden tabs in the future.
settingsTabsOrder.push('payments')
setTabIndex(settingsTabsOrder.indexOf(settingsTab ?? ''))
}
}, [displayPayments, settingsTab])

const handleTabChange = (index: number) => {
setTabIndex(index)
navigate(
Expand Down Expand Up @@ -117,9 +102,7 @@ export const SettingsPage = (): JSX.Element => {
<SettingsTab label="Singpass" icon={BiKey} />
<SettingsTab label="Twilio credentials" icon={BiMessage} />
<SettingsTab label="Webhooks" icon={BiCodeBlock} />
{displayPayments && (
<SettingsTab label="Payments" icon={BiDollar} />
)}
<SettingsTab label="Payments" icon={BiDollar} />
</TabList>
</Flex>
<TabPanels
Expand All @@ -139,11 +122,9 @@ export const SettingsPage = (): JSX.Element => {
<TabPanel>
<SettingsWebhooksPage />
</TabPanel>
{displayPayments && (
<TabPanel>
<SettingsPaymentsPage />
</TabPanel>
)}
<TabPanel>
<SettingsPaymentsPage />
</TabPanel>
</TabPanels>
<Spacer />
</Tabs>
Expand Down
123 changes: 12 additions & 111 deletions src/app/modules/form/admin-form/admin-form.payments.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { err, ok } from 'neverthrow'

import { IEncryptedFormDocument } from 'src/types'

import { featureFlags } from '../../../../../shared/constants'
import {
ErrorDto,
PaymentChannel,
Expand All @@ -19,7 +18,6 @@ import { createReqMeta } from '../../../utils/request'
import { getFormAfterPermissionChecks } from '../../auth/auth.service'
import * as AuthService from '../../auth/auth.service'
import { ControllerHandler } from '../../core/core.types'
import * as FeatureFlagService from '../../feature-flags/feature-flags.service'
import {
getStripeOauthUrl,
unlinkStripeAccountFromForm,
Expand All @@ -33,7 +31,7 @@ import { PaymentChannelNotFoundError } from './admin-form.errors'
import { JoiPaymentProduct } from './admin-form.payments.constants'
import * as AdminFormPaymentService from './admin-form.payments.service'
import { PermissionLevel } from './admin-form.types'
import { mapRouteError, verifyUserBetaflag } from './admin-form.utils'
import { mapRouteError } from './admin-form.utils'

const logger = createLoggerWithLabel(module)

Expand Down Expand Up @@ -61,44 +59,20 @@ export const handleConnectAccount: ControllerHandler<{
...createReqMeta(req),
}

// If getFeatureFlag throws a DatabaseError, we want to log it, but respond
// to the client as if the flag is not found.
const featureFlagsListResult = await FeatureFlagService.getEnabledFlags()

let featureFlagEnabled = false

if (featureFlagsListResult.isErr()) {
logger.error({
message: 'Error occurred whilst retrieving enabled feature flags',
meta: logMeta,
error: featureFlagsListResult.error,
})
} else {
featureFlagEnabled = featureFlagsListResult.value.includes(
featureFlags.payment,
)
}

// Step 1: Retrieve currently logged in user.
// Retrieve currently logged in user.
return (
getPopulatedUserById(sessionUserId)
// Step 2: Check if user has 'payment' betaflag
.andThen((user) =>
featureFlagEnabled
? ok(user)
: verifyUserBetaflag(user, featureFlags.payment),
)
.andThen((user) =>
// Step 3: Retrieve form with write permission check.
// Retrieve form with write permission check.
getFormAfterPermissionChecks({
user,
formId,
level: PermissionLevel.Write,
}),
)
// Step 4: Ensure that the form is encrypt mode.
// Ensure that the form is encrypt mode.
.andThen(checkFormIsEncryptMode)
// Step 5: Get the auth URL and state, and pass the auth URL for redirection.
// Get the auth URL and state, and pass the auth URL for redirection.
.andThen(getStripeOauthUrl)
.map(({ authUrl, state }) => {
// Save the state for validation later on, to ensure the state has not been
Expand Down Expand Up @@ -254,49 +228,25 @@ const _handleUpdatePayments: ControllerHandler<
body: req.body,
}

// If getFeatureFlag throws a DatabaseError, we want to log it, but respond
// to the client as if the flag is not found.
const featureFlagsListResult = await FeatureFlagService.getEnabledFlags()

let featureFlagEnabled = false

if (featureFlagsListResult.isErr()) {
logger.error({
message: 'Error occurred whilst retrieving enabled feature flags',
meta: logMeta,
error: featureFlagsListResult.error,
})
} else {
featureFlagEnabled = featureFlagsListResult.value.includes(
featureFlags.payment,
)
}

// Step 1: Retrieve currently logged in user.
// Retrieve currently logged in user.
return (
UserService.getPopulatedUserById(sessionUserId)
// Step 2: Check if user has 'payment' betaflag
.andThen((user) =>
featureFlagEnabled
? ok(user)
: verifyUserBetaflag(user, featureFlags.payment),
)
.andThen((user) =>
// Step 2: Retrieve form with write permission check.
// Retrieve form with write permission check.
AuthService.getFormAfterPermissionChecks({
user,
formId,
level: PermissionLevel.Write,
}),
)
.andThen(checkFormIsEncryptMode)
// Step 3: Check that the payment form has a stripe account connected
// Check that the payment form has a stripe account connected
.andThen((form) =>
form.payments_channel.channel === PaymentChannel.Unconnected
? err(new PaymentChannelNotFoundError())
: ok(form),
)
// Step 4: User has permissions, proceed to allow updating of start page
// Proceed to allow updating of start page
.andThen((form) => {
return AdminFormPaymentService.updatePayments(formId, {
...req.body,
Expand Down Expand Up @@ -482,56 +432,7 @@ export const handleGetPaymentGuideLink: ControllerHandler = async (
req,
res,
) => {
const sessionUserId = (req.session as AuthedSessionData).user._id

const logMeta = {
action: 'handleGetPaymentGuideLink',
...createReqMeta(req),
userId: sessionUserId,
}

// If getFeatureFlag throws a DatabaseError, we want to log it, but respond
// to the client as if the flag is not found.
const featureFlagsListResult = await FeatureFlagService.getEnabledFlags()

let featureFlagEnabled = false

if (featureFlagsListResult.isErr()) {
logger.error({
message: 'Error occurred whilst retrieving enabled feature flags',
meta: logMeta,
error: featureFlagsListResult.error,
})
} else {
featureFlagEnabled = featureFlagsListResult.value.includes(
featureFlags.payment,
)
}

// Step 1: Retrieve currently logged in user.
return (
UserService.getPopulatedUserById(sessionUserId)
// Step 2: Check if user has 'payment' betaflag
.andThen((user) =>
featureFlagEnabled
? ok(user)
: verifyUserBetaflag(user, featureFlags.payment),
)
// Step 3: User has permissions, proceed to get payment guide link
.map(() =>
res
.status(StatusCodes.OK)
.json(AdminFormPaymentService.getPaymentGuideLink()),
)
.mapErr((error) => {
logger.error({
message: 'Error checking if payment feature is enabled',
meta: logMeta,
error,
})

const { statusCode, errorMessage } = mapRouteError(error)
return res.status(statusCode).json({ message: errorMessage })
})
)
return res
.status(StatusCodes.OK)
.json(AdminFormPaymentService.getPaymentGuideLink())
}

0 comments on commit 1e66a8a

Please sign in to comment.