From cb9a443fb18d5c562fe73400bb7aeedb4abf3f7e Mon Sep 17 00:00:00 2001 From: Eugene Date: Thu, 25 Jul 2024 17:51:31 +0300 Subject: [PATCH] feat(pdf-marking): implements png to pdf conversion and ability to download full sigits after signing --- package.json | 1 + src/pages/sign/index.tsx | 60 +++---------- src/pages/verify/index.tsx | 104 +++++++++++++++++++++- src/types/core.ts | 2 +- src/utils/misc.ts | 10 ++- src/utils/pdf.ts | 178 +++++++++++++++++++++++++++++++++++-- src/utils/sign.ts | 33 +++++++ 7 files changed, 326 insertions(+), 62 deletions(-) create mode 100644 src/utils/sign.ts diff --git a/package.json b/package.json index fcaf0cd..5114c49 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "lodash": "4.17.21", "mui-file-input": "4.0.4", "nostr-tools": "2.7.0", + "pdf-lib": "^1.17.1", "pdfjs-dist": "^4.4.168", "react": "^18.2.0", "react-dnd": "16.0.1", diff --git a/src/pages/sign/index.tsx b/src/pages/sign/index.tsx index 1215862..14228c3 100644 --- a/src/pages/sign/index.tsx +++ b/src/pages/sign/index.tsx @@ -1,8 +1,8 @@ -import { Box, Button, FormControl, InputLabel, TextField, Typography } from '@mui/material' +import { Box, Button, Typography } from '@mui/material' import axios from 'axios' import saveAs from 'file-saver' import JSZip from 'jszip' -import _, { set } from 'lodash' +import _ from 'lodash' import { MuiFileInput } from 'mui-file-input' import { Event, verifyEvent } from 'nostr-tools' import { useEffect, useState } from 'react' @@ -13,7 +13,7 @@ import { LoadingSpinner } from '../../components/LoadingSpinner' import { NostrController } from '../../controllers' import { appPublicRoutes } from '../../routes' import { State } from '../../store/rootReducer' -import { CreateSignatureEventContent, Meta, SignedEvent, UserRole } from '../../types' +import { CreateSignatureEventContent, Meta, SignedEvent } from '../../types' import { decryptArrayBuffer, encryptArrayBuffer, @@ -34,10 +34,11 @@ import { import { DisplayMeta } from './internal/displayMeta' import styles from './style.module.scss' import { PdfFile } from '../../types/drawing.ts' -import { toFile, toPdfFile } from '../../utils/pdf.ts' +import { convertToPdfFile } from '../../utils/pdf.ts' import PdfView from '../../components/PDFView' -import { CurrentUserMark, Mark, MarkConfig, MarkConfigDetails, User } from '../../types/mark.ts' +import { CurrentUserMark, Mark, MarkConfig } from '../../types/mark.ts' import MarkFormField from './MarkFormField.tsx' +import { getLastSignersSig } from '../../utils/sign.ts' enum SignedStatus { Fully_Signed, User_Is_Next_Signer, @@ -98,7 +99,6 @@ export const SignPage = () => { const [currentUserMarks, setCurrentUserMarks] = useState([]); const [currentMarkValue, setCurrentMarkValue] = useState(''); const [isMarksCompleted, setIsMarksCompleted] = useState(false); - const [isLastUserMark, setIsLastUserMark] = useState(false); useEffect(() => { if (signers.length > 0) { @@ -330,11 +330,6 @@ export const SignPage = () => { setCurrentFileHashes(fileHashes) } - const convertToPdfFile = async (arrayBuffer: ArrayBuffer, fileName: string) => { - const file = toFile(arrayBuffer, fileName); - return toPdfFile(file); - } - const parseKeysJson = async (zip: JSZip) => { const keysFileContent = await readContentOfZipEntry( zip, @@ -491,8 +486,6 @@ export const SignPage = () => { } ) - console.log('parsed meta: ', parsedMetaJson) - setMeta(parsedMetaJson) } @@ -616,7 +609,7 @@ export const SignPage = () => { encryptionKey: string ): Promise => { // Get the current timestamp in seconds - const unixNow = Math.floor(Date.now() / 1000) + const unixNow = now() const blob = new Blob([encryptedArrayBuffer]) // Create a File object with the Blob data const file = new File([blob], `compressed.sigit`, { @@ -763,7 +756,9 @@ export const SignPage = () => { setIsLoading(true) setLoadingSpinnerDesc('Signing nostr event') - const prevSig = getLastSignersSig() + if (!meta) return; + + const prevSig = getLastSignersSig(meta, signers) if (!prevSig) return const signedEvent = await signEventForMetaFile( @@ -813,7 +808,7 @@ export const SignPage = () => { if (!arrayBuffer) return const blob = new Blob([arrayBuffer]) - const unixNow = Math.floor(Date.now() / 1000) + const unixNow = now() saveAs(blob, `exported-${unixNow}.sigit.zip`) setIsLoading(false) @@ -878,7 +873,7 @@ export const SignPage = () => { const finalZipFile = await createFinalZipFile(encryptedArrayBuffer, key) if (!finalZipFile) return - const unixNow = Math.floor(Date.now() / 1000) + const unixNow = now() saveAs(finalZipFile, `exported-${unixNow}.sigit.zip`) } @@ -915,37 +910,6 @@ export const SignPage = () => { } } - /** - * This function returns the signature of last signer - * It will be used in the content of export signature's signedEvent - */ - const getLastSignersSig = () => { - if (!meta) return null - - // if there're no signers then use creator's signature - if (signers.length === 0) { - try { - const createSignatureEvent: Event = JSON.parse(meta.createSignature) - return createSignatureEvent.sig - } catch (error) { - return null - } - } - - // get last signer - const lastSigner = signers[signers.length - 1] - - // get the signature of last signer - try { - const lastSignatureEvent: Event = JSON.parse( - meta.docSignatures[lastSigner] - ) - return lastSignatureEvent.sig - } catch (error) { - return null - } - } - if (authUrl) { return (