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

Update VxAdmin to support importing new CVR export format #3956

Merged
merged 10 commits into from
Sep 13, 2023
36 changes: 36 additions & 0 deletions apps/admin/backend/src/legacy_cast_vote_records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
CVR_BALLOT_IMAGES_SUBDIRECTORY,
CVR_BALLOT_LAYOUTS_SUBDIRECTORY,
isTestReport,
readCastVoteRecordExportMetadata,
} from '@votingworks/backend';
import {
assert,
Expand Down Expand Up @@ -40,6 +41,7 @@ import {
isCastVoteRecordWriteInValid,
isFeatureFlagEnabled,
parseCastVoteRecordReportDirectoryName,
parseCastVoteRecordReportExportDirectoryName,
SCANNER_RESULTS_FOLDER,
} from '@votingworks/utils';
import * as fs from 'fs/promises';
Expand Down Expand Up @@ -113,6 +115,40 @@ export async function listCastVoteRecordFilesOnUsb(

for (const entry of fileSearchResult.ok()) {
if (entry.type === FileSystemEntryType.Directory) {
/* c8 ignore start */
if (
isFeatureFlagEnabled(
BooleanEnvironmentVariableName.ENABLE_CONTINUOUS_EXPORT
)
) {
const directoryNameComponents =
parseCastVoteRecordReportExportDirectoryName(entry.name);
if (!directoryNameComponents) {
continue;
}
const metadataResult = await readCastVoteRecordExportMetadata(
entry.path
);
if (metadataResult.isErr()) {
continue;
}
const metadata = metadataResult.ok();
castVoteRecordFileMetadataList.push({
cvrCount: metadata.castVoteRecordReportMetadata.vxBatch
.map((batch) => batch.NumberSheets)
.reduce((sum, n) => sum + n, 0),
exportTimestamp: new Date(
metadata.castVoteRecordReportMetadata.GeneratedDate
),
isTestModeResults: directoryNameComponents.inTestMode,
name: entry.name,
path: entry.path,
scannerIds: [directoryNameComponents.machineId],
});
continue;
}
Copy link
Contributor Author

@arsalansufi arsalansufi Sep 12, 2023

Choose a reason for hiding this comment

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

Whereas previously, we could extract everything that we needed for the "list of exports on the USB" UI from the directory name, now, we have to pull some info from the metadata file.

Note that I think it's okay for us to extract this information without authenticating the export (which can be time consuming since we have to re-hash), as we aren't actually importing anything yet. If someone tries to trick the system by changing a directory name or the metadata file, the worst that they'll be able to do is get the "list of exports on the USB" UI to display something misleading. Importing will still fail.

We've applied similar principles to Java Card auth (e.g. here).

/* c8 ignore stop */

const parsedFileInfo = parseCastVoteRecordReportDirectoryName(entry.name);
if (parsedFileInfo) {
castVoteRecordFileMetadataList.push({
Expand Down