Skip to content

Commit

Permalink
Merge pull request #11250 from 18F/stages/rc-2024-09-17
Browse files Browse the repository at this point in the history
Deploy RC 415 to Production
  • Loading branch information
amirbey authored Sep 17, 2024
2 parents 0889825 + 1cf19b7 commit 4a4fcc3
Show file tree
Hide file tree
Showing 41 changed files with 792 additions and 315 deletions.
2 changes: 1 addition & 1 deletion app/controllers/concerns/personal_key_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def create_new_code
Pii::ReEncryptor.new(user: current_user, user_session: user_session).perform
active_profile.personal_key
else
PersonalKeyGenerator.new(current_user).create
PersonalKeyGenerator.new(current_user).generate!
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ def alert_user_about_personal_key_sign_in(disavowal_token)

def remove_personal_key
# for now we will regenerate a key and not show it to them so retire personal key page shows
current_user.personal_key = PersonalKeyGenerator.new(current_user).create
current_user.save!
PersonalKeyGenerator.new(current_user).generate!
user_session.delete(:personal_key)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ import type { FormStepComponentProps } from '@18f/identity-form-steps';
import GeneralError from './general-error';
import TipList from './tip-list';
import { SelfieCaptureContext } from '../context';
import {
DocumentCaptureSubheaderOne,
SelfieCaptureWithHeader,
DocumentFrontAndBackCapture,
} from './documents-and-selfie-step';
import { DocumentCaptureSubheaderOne } from './documents-and-selfie-step';
import { DocumentsCaptureStep } from './documents-step';
import { SelfieCaptureStep } from './selfie-step';
import type { ReviewIssuesStepValue } from './review-issues-step';

interface DocumentCaptureReviewIssuesProps extends FormStepComponentProps<ReviewIssuesStepValue> {
Expand Down Expand Up @@ -79,9 +77,9 @@ function DocumentCaptureReviewIssues({
]}
/>
)}
<DocumentFrontAndBackCapture defaultSideProps={defaultSideProps} value={value} />
<DocumentsCaptureStep defaultSideProps={defaultSideProps} value={value} />
{isSelfieCaptureEnabled && (
<SelfieCaptureWithHeader defaultSideProps={defaultSideProps} selfieValue={value.selfie} />
<SelfieCaptureStep defaultSideProps={defaultSideProps} selfieValue={value.selfie} />
)}
<FormStepsButton.Submit />
<Cancel />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type { FormStep } from '@18f/identity-form-steps';
import { getConfigValue } from '@18f/identity-config';
import { UploadFormEntriesError } from '../services/upload';
import DocumentsAndSelfieStep from './documents-and-selfie-step';
import SelfieStep from './selfie-step';
import DocumentsStep from './documents-step';
import InPersonPrepareStep from './in-person-prepare-step';
import InPersonLocationPostOfficeSearchStep from './in-person-location-post-office-search-step';
import InPersonLocationFullAddressEntryPostOfficeSearchStep from './in-person-location-full-address-entry-post-office-search-step';
Expand All @@ -21,7 +23,7 @@ import { RetrySubmissionError } from './submission-complete';
import SuspenseErrorBoundary from './suspense-error-boundary';
import SubmissionInterstitial from './submission-interstitial';
import withProps from '../higher-order/with-props';
import { InPersonContext } from '../context';
import { InPersonContext, SelfieCaptureContext } from '../context';

interface DocumentCaptureProps {
/**
Expand All @@ -37,6 +39,7 @@ function DocumentCapture({ onStepChange = () => {} }: DocumentCaptureProps) {
const { t } = useI18n();
const { flowPath } = useContext(UploadContext);
const { trackSubmitEvent, trackVisitEvent } = useContext(AnalyticsContext);
const { isSelfieCaptureEnabled, docAuthSeparatePagesEnabled } = useContext(SelfieCaptureContext);
const { inPersonFullAddressEntryEnabled, inPersonURL, skipDocAuth, skipDocAuthFromHandoff } =
useContext(InPersonContext);
useDidUpdateEffect(onStepChange, [stepName]);
Expand All @@ -51,11 +54,25 @@ function DocumentCapture({ onStepChange = () => {} }: DocumentCaptureProps) {
: InPersonLocationPostOfficeSearchStep;

// Define different states to be used in human readable array declaration
const documentFormStep: FormStep = {
name: 'documents',
const documentAndSelfieFormStep: FormStep = {
name: 'documentsAndSelfie',
form: DocumentsAndSelfieStep,
title: t('doc_auth.headings.document_capture'),
};
const documentFormStep: FormStep = {
name: 'documents',
form: DocumentsStep,
title: t('doc_auth.headings.document_capture'), // might want to change title to isolated doc capture heading
};
const selfieFormStep: FormStep = {
name: 'selfie',
form: SelfieStep,
title: '', // TODO: replace with yml selfie_capture (Ticket LG-14392)
};
const documentsFormSteps: FormStep[] =
isSelfieCaptureEnabled && docAuthSeparatePagesEnabled && submissionError === undefined
? [documentFormStep, selfieFormStep]
: [documentAndSelfieFormStep];
const reviewFormStep: FormStep = {
name: 'review',
form:
Expand Down Expand Up @@ -131,10 +148,12 @@ function DocumentCapture({ onStepChange = () => {} }: DocumentCaptureProps) {
: ([prepareFormStep, locationFormStep, flowPath === 'hybrid' && hybridFormStep].filter(
Boolean,
) as FormStep[]);

const defaultSteps: FormStep[] = submissionError
? ([reviewFormStep] as FormStep[]).concat(inPersonSteps)
: ([documentFormStep] as FormStep[]);
const reviewAfterFailedSteps = [reviewFormStep] as FormStep[];
const reviewWithInPersonSteps = reviewAfterFailedSteps.concat(inPersonSteps);
const afterSubmissionErrorSteps = docAuthSeparatePagesEnabled
? reviewAfterFailedSteps
: reviewWithInPersonSteps;
const defaultSteps: FormStep[] = submissionError ? afterSubmissionErrorSteps : documentsFormSteps;

// If the user got here by opting-in to in-person proofing, when skipDocAuth === true,
// then set steps to inPersonSteps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ function DocumentSideAcuantCapture({
}: DocumentSideAcuantCaptureProps) {
const error = errors.find(({ field }) => field === side)?.error;
const { changeStepCanComplete } = useContext(FormStepsContext);
const { isSelfieCaptureEnabled, isSelfieDesktopTestMode } = useContext(SelfieCaptureContext);
const { isSelfieCaptureEnabled, isSelfieDesktopTestMode, docAuthSeparatePagesEnabled } =
useContext(SelfieCaptureContext);
const isUploadAllowed = isSelfieDesktopTestMode || !isSelfieCaptureEnabled;

const stepCanComplete = docAuthSeparatePagesEnabled ? undefined : true;
return (
<AcuantCapture
ref={registerField(side, { isRequired: true })}
Expand All @@ -79,7 +80,7 @@ function DocumentSideAcuantCapture({
onError(new Error(t('doc_auth.errors.doc.resubmit_failed_image')), { field: side });
changeStepCanComplete(false);
} else {
changeStepCanComplete(true);
changeStepCanComplete(stepCanComplete);
}
}}
onCameraAccessDeclined={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import {
import { PageHeading } from '@18f/identity-components';
import { Cancel } from '@18f/identity-verify-flow';
import HybridDocCaptureWarning from './hybrid-doc-capture-warning';
import DocumentSideAcuantCapture from './document-side-acuant-capture';
import { SelfieCaptureStep } from './selfie-step';
import { DocumentsCaptureStep } from './documents-step';
import TipList from './tip-list';
import {
DefaultSideProps,
DocumentsAndSelfieStepValue,
} from '../interface/documents-image-selfie-value';
import { DeviceContext, SelfieCaptureContext, UploadContext } from '../context';

export function DocumentCaptureSubheaderOne({
Expand All @@ -20,83 +25,12 @@ export function DocumentCaptureSubheaderOne({
const { t } = useI18n();
return (
<h2>
<hr className="margin-y-5" />
{isSelfieCaptureEnabled && '1. '}
{t('doc_auth.headings.document_capture_subheader_id')}
</h2>
);
}

export function SelfieCaptureWithHeader({
defaultSideProps,
selfieValue,
}: {
defaultSideProps: DefaultSideProps;
selfieValue: ImageValue;
}) {
const { t } = useI18n();
return (
<>
<hr className="margin-y-5" />
<h2>2. {t('doc_auth.headings.document_capture_subheader_selfie')}</h2>
<p>{t('doc_auth.info.selfie_capture_content')}</p>
<TipList
title={t('doc_auth.tips.document_capture_selfie_selfie_text')}
titleClassName="margin-bottom-0 text-bold"
items={[
t('doc_auth.tips.document_capture_selfie_text1'),
t('doc_auth.tips.document_capture_selfie_text2'),
t('doc_auth.tips.document_capture_selfie_text3'),
t('doc_auth.tips.document_capture_selfie_text4'),
]}
/>
<DocumentSideAcuantCapture
{...defaultSideProps}
key="selfie"
side="selfie"
value={selfieValue}
/>
</>
);
}

export function DocumentFrontAndBackCapture({
defaultSideProps,
value,
}: {
defaultSideProps: DefaultSideProps;
value: Record<string, ImageValue>;
}) {
type DocumentSide = 'front' | 'back';
const documentsSides: DocumentSide[] = ['front', 'back'];
return (
<>
{documentsSides.map((side) => (
<DocumentSideAcuantCapture
{...defaultSideProps}
key={side}
side={side}
value={value[side]}
/>
))}
</>
);
}

type ImageValue = Blob | string | null | undefined;

interface DocumentsAndSelfieStepValue {
front: ImageValue;
back: ImageValue;
selfie: ImageValue;
front_image_metadata?: string;
back_image_metadata?: string;
}

type DefaultSideProps = Pick<
FormStepComponentProps<DocumentsAndSelfieStepValue>,
'registerField' | 'onChange' | 'errors' | 'onError'
>;

export default function DocumentsAndSelfieStep({
value = {},
onChange = () => {},
Expand All @@ -109,11 +43,9 @@ export default function DocumentsAndSelfieStep({
const { isLastStep } = useContext(FormStepsContext);
const { flowPath } = useContext(UploadContext);
const { isSelfieCaptureEnabled } = useContext(SelfieCaptureContext);

const pageHeaderText = isSelfieCaptureEnabled
? t('doc_auth.headings.document_capture_with_selfie')
: t('doc_auth.headings.document_capture');

const defaultSideProps: DefaultSideProps = {
registerField,
onChange,
Expand All @@ -136,9 +68,9 @@ export default function DocumentsAndSelfieStep({
t('doc_auth.tips.document_capture_id_text3'),
].concat(!isMobile ? [t('doc_auth.tips.document_capture_id_text4')] : [])}
/>
<DocumentFrontAndBackCapture defaultSideProps={defaultSideProps} value={value} />
<DocumentsCaptureStep defaultSideProps={defaultSideProps} value={value} />
{isSelfieCaptureEnabled && (
<SelfieCaptureWithHeader defaultSideProps={defaultSideProps} selfieValue={value.selfie} />
<SelfieCaptureStep defaultSideProps={defaultSideProps} selfieValue={value.selfie} />
)}
{isLastStep ? <FormStepsButton.Submit /> : <FormStepsButton.Continue />}
<Cancel />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useContext } from 'react';
import { useI18n } from '@18f/identity-react-i18n';
import { FormStepComponentProps, FormStepsButton } from '@18f/identity-form-steps';
import { PageHeading } from '@18f/identity-components';
import { Cancel } from '@18f/identity-verify-flow';
import HybridDocCaptureWarning from './hybrid-doc-capture-warning';
import TipList from './tip-list';
import { DeviceContext, SelfieCaptureContext, UploadContext } from '../context';
import {
ImageValue,
DefaultSideProps,
DocumentsAndSelfieStepValue,
} from '../interface/documents-image-selfie-value';
import DocumentSideAcuantCapture from './document-side-acuant-capture';

export function DocumentsCaptureStep({
defaultSideProps,
value,
}: {
defaultSideProps: DefaultSideProps;
value: Record<string, ImageValue>;
}) {
type DocumentSide = 'front' | 'back';
const documentsSides: DocumentSide[] = ['front', 'back'];
return (
<>
{documentsSides.map((side) => (
<DocumentSideAcuantCapture
{...defaultSideProps}
key={side}
side={side}
value={value[side]}
/>
))}
</>
);
}

export function DocumentCaptureSubheaderOne() {
const { t } = useI18n();
return (
<h2>
<hr className="margin-y-5" />
{'1. '}
{t('doc_auth.headings.document_capture_subheader_id')}
</h2>
);
}

export default function DocumentsStep({
value = {},
onChange = () => {},
errors = [],
onError = () => {},
registerField = () => undefined,
}: FormStepComponentProps<DocumentsAndSelfieStepValue>) {
const { t } = useI18n();
const { isMobile } = useContext(DeviceContext);
const { flowPath } = useContext(UploadContext);
const { isSelfieCaptureEnabled } = useContext(SelfieCaptureContext);
const pageHeaderText = isSelfieCaptureEnabled
? t('doc_auth.headings.document_capture_with_selfie')
: t('doc_auth.headings.document_capture');
const defaultSideProps: DefaultSideProps = {
registerField,
onChange,
errors,
onError,
};
return (
<>
{flowPath === 'hybrid' && <HybridDocCaptureWarning className="margin-bottom-4" />}
<PageHeading>{pageHeaderText}</PageHeading>
<DocumentCaptureSubheaderOne />
<TipList
titleClassName="margin-bottom-0 text-bold"
title={t('doc_auth.tips.document_capture_selfie_id_header_text')}
items={[
t('doc_auth.tips.document_capture_id_text1'),
t('doc_auth.tips.document_capture_id_text2'),
t('doc_auth.tips.document_capture_id_text3'),
].concat(!isMobile ? [t('doc_auth.tips.document_capture_id_text4')] : [])}
/>
<DocumentsCaptureStep defaultSideProps={defaultSideProps} value={value} />
<FormStepsButton.Continue />
<Cancel />
</>
);
}
Loading

0 comments on commit 4a4fcc3

Please sign in to comment.