chore: quality of life improvements (#449)

This commit is contained in:
2022-04-13 22:16:34 +02:00
committed by GitHub
parent e916177569
commit c10817716e
34 changed files with 14038 additions and 11804 deletions

View File

@@ -1,5 +1,19 @@
import React, { useState, useCallback, useContext, createContext, useEffect } from 'react';
import { readMessage, readKey, decrypt as pgpDecrypt, readPrivateKeys, readPrivateKey, generateKey } from 'openpgp';
import React, {
useState,
useCallback,
useContext,
createContext,
useEffect,
ReactNode,
} from 'react';
import {
readMessage,
readKey,
decrypt as pgpDecrypt,
readPrivateKeys,
readPrivateKey,
generateKey,
} from 'openpgp';
import GithubContext from './Github';
import FileType from '../types/File';
import { createFile } from '../helpers/files';
@@ -9,11 +23,15 @@ interface DecryptionContextType {
privateKey: string | undefined;
createKey: (name: string, email: string) => void;
deleteKey: () => void;
files: {[id: string]: FileType};
files: { [id: string]: FileType };
addFile: (file: File) => Promise<void>;
deleteFile: (id: string) => void;
}
type DecryptionProviderProps = {
children: ReactNode;
};
const removeExtension = (name: string) => {
const parts = name.split('.');
parts.pop();
@@ -24,21 +42,32 @@ const DecryptionContext = createContext<DecryptionContextType>({
publicKey: undefined,
privateKey: undefined,
files: {},
createKey: async () => { throw new Error('Not using provider'); },
deleteKey: async () => { throw new Error('Not using provider'); },
addFile: async () => { throw new Error('Not using provider'); },
deleteFile: async () => { throw new Error('Not using provider'); },
createKey: async () => {
throw new Error('Not using provider');
},
deleteKey: async () => {
throw new Error('Not using provider');
},
addFile: async () => {
throw new Error('Not using provider');
},
deleteFile: async () => {
throw new Error('Not using provider');
},
});
const decrypt = async (privateKey: string, keys: string[], content: string) => {
const armoredKeys = await Promise.all(
keys.map(key => readKey({ armoredKey: key })),
keys.map((key) => readKey({ armoredKey: key }))
);
const message = await readMessage({ armoredMessage: content });
const encrypted = await pgpDecrypt({
message,
decryptionKeys: await readPrivateKeys({ armoredKeys: privateKey }),
verificationKeys: armoredKeys.reduce<any>((output, key: any) => [...output, ...key], []),
verificationKeys: armoredKeys.reduce<any>(
(output, key: any) => [...output, ...key],
[]
),
});
const { data } = encrypted;
const blob = new Blob([data as any], {
@@ -47,7 +76,7 @@ const decrypt = async (privateKey: string, keys: string[], content: string) => {
return blob;
};
const DecryptionProvider: React.FC = ({
const DecryptionProvider: React.FC<DecryptionProviderProps> = ({
children,
}) => {
const { keys } = useContext(GithubContext);
@@ -55,12 +84,15 @@ const DecryptionProvider: React.FC = ({
const [publicKey, setPublicKey] = useState<string | undefined>(undefined);
const [files, setFiles] = useState<DecryptionContextType['files']>({});
const deleteFile = useCallback((id: string) => {
delete files[id];
setFiles({
...files,
});
}, [files]);
const deleteFile = useCallback(
(id: string) => {
delete files[id];
setFiles({
...files,
});
},
[files]
);
useEffect(() => {
const run = async () => {
@@ -83,29 +115,34 @@ const DecryptionProvider: React.FC = ({
const createKey = async () => {
const key = await generateKey({
userIDs: [{ name: 'unknown unknown', email: 'unknown@unknown.foo'}],
userIDs: [{ name: 'unknown unknown', email: 'unknown@unknown.foo' }],
curve: 'ed25519',
});
setPrivateKey(key.privateKey);
setPublicKey(key.publicKey);
localStorage.setItem('key', key.privateKey);
}
};
const addFile = useCallback(async (file: File) => {
if (!keys || !privateKey) return;
const addedFile = createFile(setFiles, removeExtension(file.name));
const reader = new FileReader()
const addFile = useCallback(
async (file: File) => {
if (!keys || !privateKey) {
return;
}
const addedFile = createFile(setFiles, removeExtension(file.name));
const reader = new FileReader();
reader.onabort = addedFile.setFailed,
reader.onerror = addedFile.setFailed,
reader.onload = () => {
addedFile.setContent(
decrypt(privateKey, keys, reader.result as string),
);
}
reader.readAsText(file);
}, [keys, privateKey]);
(reader.onabort = addedFile.setFailed),
(reader.onerror = addedFile.setFailed),
(reader.onload = () => {
addedFile.setContent(
decrypt(privateKey, keys, reader.result as string)
);
});
reader.readAsText(file);
},
[keys, privateKey]
);
return (
<DecryptionContext.Provider
@@ -124,8 +161,6 @@ const DecryptionProvider: React.FC = ({
);
};
export {
DecryptionProvider,
};
export { DecryptionProvider };
export default DecryptionContext;;
export default DecryptionContext;

View File

@@ -1,31 +1,50 @@
import React, { useState, useCallback, useContext, createContext } from 'react';
import React, {
useState,
useCallback,
useContext,
createContext,
ReactNode,
} from 'react';
import * as openpgp from 'openpgp';
import GithubContext from './Github';
import { createFile } from '../helpers/files';
import FileType from '../types/File';
interface EncryptionContextType {
files: {[id: string]: FileType};
files: { [id: string]: FileType };
addFile: (file: File) => Promise<void>;
addText: (text: string, name: string) => Promise<void>;
deleteFile: (id: string) => void;
}
type EncryptionProviderProps = {
children: ReactNode;
};
const EncryptionContext = createContext<EncryptionContextType>({
files: {},
addFile: async () => { throw new Error('Not using provider'); },
addText: async () => { throw new Error('Not using provider'); },
deleteFile: async () => { throw new Error('Not using provider'); },
addFile: async () => {
throw new Error('Not using provider');
},
addText: async () => {
throw new Error('Not using provider');
},
deleteFile: async () => {
throw new Error('Not using provider');
},
});
const encrypt = async (keys: string[], content: string) => {
const armoredKeys = await Promise.all(
keys.map(key => openpgp.readKeys({ armoredKeys: key })),
keys.map((key) => openpgp.readKeys({ armoredKeys: key }))
);
const message = await openpgp.createMessage({ text: content });
const encrypted = await openpgp.encrypt({
message,
encryptionKeys: armoredKeys.reduce<any>((output, key: any) => [...output, ...key], []),
encryptionKeys: armoredKeys.reduce<any>(
(output, key: any) => [...output, ...key],
[]
),
});
const data = encrypted;
const blob = new Blob([data as any], {
@@ -34,41 +53,50 @@ const encrypt = async (keys: string[], content: string) => {
return blob;
};
const EncryptionProvider: React.FC = ({
const EncryptionProvider: React.FC<EncryptionProviderProps> = ({
children,
}) => {
const { username, keys } = useContext(GithubContext);
const [files, setFiles] = useState<EncryptionContextType['files']>({});
const deleteFile = useCallback((id: string) => {
delete files[id];
setFiles({
...files,
});
}, [files]);
const deleteFile = useCallback(
(id: string) => {
delete files[id];
setFiles({
...files,
});
},
[files]
);
const addFile = useCallback(async (file: File) => {
if (!keys) return;
const addedFile = createFile(setFiles, `${file.name}.acs`);
const reader = new FileReader()
const addFile = useCallback(
async (file: File) => {
if (!keys) {
return;
}
const addedFile = createFile(setFiles, `${file.name}.acs`);
const reader = new FileReader();
reader.onabort = addedFile.setFailed,
reader.onerror = addedFile.setFailed,
reader.onload = () => {
addedFile.setContent(
encrypt(keys, reader.result as string),
);
}
reader.readAsText(file)
}, [keys, username]);
(reader.onabort = addedFile.setFailed),
(reader.onerror = addedFile.setFailed),
(reader.onload = () => {
addedFile.setContent(encrypt(keys, reader.result as string));
});
reader.readAsText(file);
},
[keys, username]
);
const addText = useCallback(async (text: string, name: string) => {
if (!keys) return;
const file = createFile(setFiles, `${name}.txt.asc`);
file.setContent(
encrypt(keys, text),
);
}, [keys, username]);
const addText = useCallback(
async (text: string, name: string) => {
if (!keys) {
return;
}
const file = createFile(setFiles, `${name}.txt.asc`);
file.setContent(encrypt(keys, text));
},
[keys, username]
);
return (
<EncryptionContext.Provider
@@ -84,9 +112,6 @@ const EncryptionProvider: React.FC = ({
);
};
export {
EncryptionProvider,
};
export { EncryptionProvider };
export default EncryptionContext;

View File

@@ -1,4 +1,4 @@
import React, { createContext } from 'react';
import React, { createContext, ReactNode } from 'react';
declare var data: any;
@@ -7,19 +7,17 @@ interface GithubContextType {
keys?: string[];
}
type GithubProviderProps = {
children: ReactNode;
};
const GithubContext = createContext<GithubContextType>(data);
const GithubProvider: React.FC = ({
children,
}) => (
<GithubContext.Provider
value={{ ...data }}
>
const GithubProvider: React.FC<GithubProviderProps> = ({ children }) => (
<GithubContext.Provider value={{ ...data }}>
{children}
</GithubContext.Provider>
);
export {
GithubProvider,
};
export { GithubProvider };
export default GithubContext;