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

build: release v6.92.0 #6932

Merged
merged 16 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,38 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [v6.92.0](https://github.com/opengovsg/FormSG/compare/v6.92.0...v6.92.0)

- feat: set secret key input to password type on activation modal [`#6933`](https://github.com/opengovsg/FormSG/pull/6933)

#### [v6.92.0](https://github.com/opengovsg/FormSG/compare/v6.91.1...v6.92.0)

> 28 November 2023

- fix: add myinfo errors to error map for storage-mode submissions [`#6931`](https://github.com/opengovsg/FormSG/pull/6931)
- feat(FE): set secret key input to password type [`#6930`](https://github.com/opengovsg/FormSG/pull/6930)
- feat: add prefills for variable payments [`#6899`](https://github.com/opengovsg/FormSG/pull/6899)
- chore: update package repo for font-wqy-zenhei package [`#6920`](https://github.com/opengovsg/FormSG/pull/6920)
- feat(payments): add paynow payment method [`#6900`](https://github.com/opengovsg/FormSG/pull/6900)
- build: merge Release 6.91.1 into develop [`#6925`](https://github.com/opengovsg/FormSG/pull/6925)
- fix(deps): bump libphonenumber-js from 1.10.48 to 1.10.51 in /shared [`#6926`](https://github.com/opengovsg/FormSG/pull/6926)
- build: release 6.91.1 hotfix [`#6924`](https://github.com/opengovsg/FormSG/pull/6924)
- fix(deps): bump type-fest from 4.8.1 to 4.8.2 in /shared [`#6923`](https://github.com/opengovsg/FormSG/pull/6923)
- chore(deps-dev): bump @types/lodash from 4.14.201 to 4.14.202 in /shared [`#6921`](https://github.com/opengovsg/FormSG/pull/6921)
- build: release v6.91.0 (#6918) [`#6919`](https://github.com/opengovsg/FormSG/pull/6919)
- fix(markdown): refine regex to handle newlines after indentation groups [`#6917`](https://github.com/opengovsg/FormSG/pull/6917)
- fix: omit isVisible property from webhook response [`#6907`](https://github.com/opengovsg/FormSG/pull/6907)
- feat: charts [`#6790`](https://github.com/opengovsg/FormSG/pull/6790)
- build: merge release 6.90.0 to develop [`#6914`](https://github.com/opengovsg/FormSG/pull/6914)
- chore: bump version to v6.92.0 [`72fac02`](https://github.com/opengovsg/FormSG/commit/72fac021a92df588be577c25690b49e96796387d)

#### [v6.91.1](https://github.com/opengovsg/FormSG/compare/v6.91.0...v6.91.1)

> 23 November 2023

- build: release v6.91.0 [`#6918`](https://github.com/opengovsg/FormSG/pull/6918)
- Revert "fix: refine regex to handle newlines after indentation groups" [`10955ed`](https://github.com/opengovsg/FormSG/commit/10955ed7bbac0fcb7872ab0b49be43ba3dd3acb5)
- chore: bump version to 6.91.1 [`e74904b`](https://github.com/opengovsg/FormSG/commit/e74904ba118db029b876590edbdd3d53a04fa6e9)

#### [v6.91.0](https://github.com/opengovsg/FormSG/compare/v6.90.0...v6.91.0)

Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.development
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ RUN apk update && apk upgrade && \
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

# Chinese fonts
RUN echo @edge http://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && apk add wqy-zenhei@edge
# This package is needed to render Chinese characters in autoreply PDFs
RUN apk add font-wqy-zenhei --repository https://dl-cdn.alpinelinux.org/alpine/edge/community

# Avoid using globs as there seems to be some inconsistency in the way dockerfile handles globs
# * https://github.com/moby/moby/issues/15858
Expand Down
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "form-frontend",
"version": "6.91.0",
"version": "6.92.0",
"homepage": ".",
"private": true,
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export const SecretKeyVerification = ({
<Stack direction="row" spacing="0.5rem">
<Skeleton isLoaded={!isLoading} w="100%">
<Input
type="password"
isDisabled={isLoading}
{...register(SECRET_KEY_NAME, secretKeyValidationRules)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export const SecretKeyActivationModal = ({
<FormLabel>Enter or upload Secret Key</FormLabel>
<Stack direction="row" spacing="0.5rem">
<Input
type="password"
{...register('secretKey', {
required: "Please enter the form's secret key",
pattern: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { useSearchParams } from 'react-router-dom'
import { Box, Stack } from '@chakra-ui/react'
import { isEmpty, times } from 'lodash'

import { PAYMENT_VARIABLE_INPUT_AMOUNT_FIELD_ID } from '~shared/constants'
import { BasicField, FormFieldDto } from '~shared/types/field'
import { FormColorTheme, FormResponseMode, LogicDto } from '~shared/types/form'
import { centsToDollars } from '~shared/utils/payments'

import InlineMessage from '~components/InlineMessage'
import { FormFieldValues } from '~templates/Field'
Expand Down Expand Up @@ -97,6 +99,18 @@ export const FormFields = ({
}, {})
}, [augmentedFormFields, fieldPrefillMap])

// payment prefills - only for variable payments
if (searchParams.has(PAYMENT_VARIABLE_INPUT_AMOUNT_FIELD_ID)) {
const paymentParamValue = Number.parseInt(
searchParams.get(PAYMENT_VARIABLE_INPUT_AMOUNT_FIELD_ID) ?? '',
10,
)
if (Number.isInteger(paymentParamValue) && paymentParamValue > 0) {
const paymentAmount = centsToDollars(Number(paymentParamValue))
defaultFormValues[PAYMENT_VARIABLE_INPUT_AMOUNT_FIELD_ID] = paymentAmount
}
}

const formMethods = useForm<FormFieldValues>({
defaultValues: defaultFormValues,
mode: 'onTouched',
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "FormSG",
"description": "Form Manager for Government",
"version": "6.91.1",
"version": "6.92.0",
"homepage": "https://form.gov.sg",
"authors": [
"FormSG <[email protected]>"
Expand Down
36 changes: 18 additions & 18 deletions shared/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion shared/types/form/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../../constants/form'
import { DateString } from '../generic'
import { FormLogic, LogicDto } from './form_logic'
import { PaymentChannel, PaymentType } from '../payment'
import { PaymentChannel, PaymentMethodType, PaymentType } from '../payment'
import { Product } from './product'

export type FormId = Opaque<string, 'FormId'>
Expand Down Expand Up @@ -72,6 +72,7 @@ export enum FormResponseMode {
}

export type FormPaymentsChannel = {
payment_methods?: PaymentMethodType[]
channel: PaymentChannel
target_account_id: string
publishable_key: string
Expand Down
5 changes: 5 additions & 0 deletions shared/types/payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export enum PaymentChannel {
Stripe = 'Stripe',
// for extensibility to future payment options
}

export enum PaymentMethodType {
Paynow = 'Paynow',
}

export enum PaymentType {
Fixed = 'Fixed',
Variable = 'Variable',
Expand Down
1 change: 1 addition & 0 deletions src/app/models/__tests__/form.server.model.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const PAYMENTS_DEFAULTS = {
channel: PaymentChannel.Unconnected,
target_account_id: '',
publishable_key: '',
payment_methods: [],
},
payments_field: {
enabled: false,
Expand Down
6 changes: 6 additions & 0 deletions src/app/models/form.server.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ const EncryptedFormSchema = new Schema<IEncryptedFormSchema>({
default: '',
validate: [/^\S*$/i, 'publishable_key must not contain whitespace.'],
},
payment_methods: {
type: [String],
default: [],
},
},

payments_field: formPaymentsFieldSchema,
Expand Down Expand Up @@ -244,6 +248,7 @@ EncryptedFormDocumentSchema.methods.addPaymentAccountId = async function ({
channel: PaymentChannel.Stripe,
target_account_id: accountId,
publishable_key: publishableKey,
payment_methods: [],
}
}
return this.save()
Expand All @@ -254,6 +259,7 @@ EncryptedFormDocumentSchema.methods.removePaymentAccount = async function () {
channel: PaymentChannel.Unconnected,
target_account_id: '',
publishable_key: '',
payment_methods: [],
}
if (this.payments_field) {
this.payments_field.enabled = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import {
createEncryptedSubmissionDto,
getPaymentAmount,
getPaymentIntentDescription,
getStripePaymentMethod,
mapRouteError,
} from './encrypt-submission.utils'

Expand Down Expand Up @@ -487,10 +488,7 @@ const _createPaymentSubmission = async ({
const createPaymentIntentParams: Stripe.PaymentIntentCreateParams = {
amount,
currency: paymentConfig.defaultCurrency,
// determine payment methods available based on stripe settings
automatic_payment_methods: {
enabled: true,
},
...getStripePaymentMethod(form),
description: getPaymentIntentDescription(form, paymentProducts),
receipt_email: paymentReceiptEmail,
metadata,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { StatusCodes } from 'http-status-codes'
import moment from 'moment-timezone'
import Stripe from 'stripe'

import {
FormPaymentsField,
PaymentChannel,
PaymentFieldsDto,
PaymentMethodType,
PaymentType,
StorageModeSubmissionContentDto,
StorageModeSubmissionDto,
Expand Down Expand Up @@ -53,6 +56,14 @@ import {
FormNotFoundError,
PrivateFormError,
} from '../../form/form.errors'
import {
MyInfoCookieStateError,
MyInfoHashDidNotMatchError,
MyInfoHashingError,
MyInfoInvalidLoginCookieError,
MyInfoMissingHashError,
MyInfoMissingLoginCookieError,
} from '../../myinfo/myinfo.errors'
import { MyInfoKey } from '../../myinfo/myinfo.types'
import { PaymentNotFoundError } from '../../payments/payments.errors'
import {
Expand Down Expand Up @@ -120,12 +131,32 @@ const errorMapper: MapRouteError = (
case MissingJwtError:
case VerifyJwtError:
case InvalidJwtError:
case MyInfoMissingLoginCookieError:
case MyInfoCookieStateError:
case MyInfoInvalidLoginCookieError:
case MalformedVerifiedContentError:
return {
statusCode: StatusCodes.UNAUTHORIZED,
errorMessage:
'Something went wrong with your login. Please try logging in and submitting again.',
}
case MyInfoMissingHashError:
return {
statusCode: StatusCodes.GONE,
errorMessage:
'MyInfo verification expired, please refresh and try again.',
}
case MyInfoHashDidNotMatchError:
return {
statusCode: StatusCodes.UNAUTHORIZED,
errorMessage: 'MyInfo verification failed.',
}
case MyInfoHashingError:
return {
statusCode: StatusCodes.SERVICE_UNAVAILABLE,
errorMessage:
'MyInfo verification unavailable, please try again later.',
}
case MissingUserError:
return {
statusCode: StatusCodes.UNPROCESSABLE_ENTITY,
Expand Down Expand Up @@ -405,3 +436,24 @@ export const formatMyInfoStorageResponseData = (
})
}
}

export const getStripePaymentMethod = (
form: IPopulatedEncryptedForm,
): Omit<Stripe.PaymentIntentCreateParams, 'amount' | 'currency'> => {
const isPaynowOnly =
form.payments_channel.payment_methods?.includes(PaymentMethodType.Paynow) &&
form.payments_channel.payment_methods?.length === 1
const stripePaynowOnly =
form.payments_channel.channel === PaymentChannel.Stripe && isPaynowOnly

if (stripePaynowOnly) {
return {
payment_method_types: ['paynow'],
}
}
return {
automatic_payment_methods: {
enabled: true,
},
}
}
Loading