minor refactoring and bugfixes (#22)

This commit is contained in:
tsukino
2023-11-10 00:10:12 -08:00
committed by GitHub
parent b68910ad5d
commit 7c95e9e6f8
16 changed files with 120 additions and 119 deletions

View File

@@ -1,5 +1,5 @@
{
root: true,
"root": true,
"extends": ["prettier", "plugin:@typescript-eslint/recommended"],
"plugins": ["prettier", "@typescript-eslint"],
"parser": "@typescript-eslint/parser",
@@ -7,6 +7,7 @@
"prettier/prettier": "error",
"@typescript-eslint/no-explicit-any": 1,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/ban-ts-comment": 0,
"no-undef": "error",
"padding-line-between-statements": "error"
},

View File

@@ -10,6 +10,7 @@
"clone:tlsn": "bash ./utils/download-tlsn.sh",
"build:wasm": "wasm-pack build --target web wasm/prover",
"build": "NODE_ENV=production node utils/build.js",
"build:webpack": "NODE_ENV=production webpack --config webpack.config.js",
"dev": "NODE_ENV=development node utils/webserver.js",
"lint": "eslint .",
"lint:fix": "eslint . --fix"

View File

@@ -68,9 +68,7 @@ function OneRequestHistory(props: { requestId: string }): ReactElement {
</div>
<div className="flex flex-row">
<div className="font-bold text-slate-400">Host:</div>
<div className="ml-2 text-slate-800">
{requestUrl?.host}
</div>
<div className="ml-2 text-slate-800">{requestUrl?.host}</div>
</div>
<div className="flex flex-row">
<div className="font-bold text-slate-400">Notary API:</div>
@@ -95,7 +93,9 @@ function OneRequestHistory(props: { requestId: string }): ReactElement {
</div>
<div
className="flex flex-row flex-grow-0 gap-2 self-end items-center justify-end px-2 py-1 bg-slate-100 text-slate-300 hover:bg-slate-200 hover:text-slate-500 hover:font-bold"
onClick={() => download(`${request?.id}.json`, JSON.stringify(request?.proof))}
onClick={() =>
download(`${request?.id}.json`, JSON.stringify(request?.proof))
}
>
<Icon className="" fa="fa-solid fa-download" size={1} />
<span className="text-xs font-bold">Download</span>

View File

@@ -8,8 +8,6 @@ export default function Notarize(): ReactElement {
const request = useRequestHistory(params.requestId);
return (
<div className="flex flex-col flex-nowrap flex-grow">
{request?.id}
</div>
<div className="flex flex-col flex-nowrap flex-grow">{request?.id}</div>
);
}

View File

@@ -7,7 +7,7 @@ import {
} from '../../utils/storage';
export default function Options(): ReactElement {
const [notary, setNotary] = useState('http://localhost:7047');
const [notary, setNotary] = useState('https://localhost:7047');
const [proxy, setProxy] = useState('ws://127.0.0.1:55688');
const [dirty, setDirty] = useState(false);

View File

@@ -1,18 +1,21 @@
import React, { ReactNode, ReactElement, useState } from 'react';
import React, {
ReactNode,
ReactElement,
useState,
MouseEventHandler,
} from 'react';
import { useParams, useLocation, useNavigate } from 'react-router';
import c from 'classnames';
import { useRequestHistory } from '../../reducers/history';
import RequestBuilder from '../../pages/RequestBuilder';
import Icon from '../../components/Icon';
import { download } from '../../utils/misc';
export default function ProofViewer(): ReactElement {
const {requestId} = useParams<{ requestId: string }>();
const { requestId } = useParams<{ requestId: string }>();
const request = useRequestHistory(requestId);
const navigate = useNavigate();
const [ tab, setTab ] = useState('sent');
const loc = useLocation();
const [tab, setTab] = useState('sent');
return (
<div className="flex flex-col w-full py-2 gap-2 flex-grow">
<div className="flex flex-col px-2">
@@ -25,22 +28,19 @@ export default function ProofViewer(): ReactElement {
onClick={() => navigate(-1)}
fa="fa-solid fa-xmark"
/>
<TabLabel
onClick={() => setTab('sent')}
active={tab === 'sent'}
>
<TabLabel onClick={() => setTab('sent')} active={tab === 'sent'}>
Sent
</TabLabel>
<TabLabel
onClick={() => setTab('recv')}
active={tab === 'recv'}
>
<TabLabel onClick={() => setTab('recv')} active={tab === 'recv'}>
Recv
</TabLabel>
<div className="flex flex-row flex-grow items-center justify-end">
<button
<button
className="button"
onClick={() => download(request.id, JSON.stringify(request.proof))}
onClick={() => {
if (!request) return;
download(request.id, JSON.stringify(request.proof));
}}
>
Download
</button>
@@ -51,19 +51,19 @@ export default function ProofViewer(): ReactElement {
{tab === 'sent' && (
<textarea
className="w-full resize-none bg-slate-100 text-slate-800 border p-2 text-[10px] break-all h-full outline-none font-mono"
value={request.verification?.sent}
value={request?.verification?.sent}
></textarea>
)}
{tab === 'recv' && (
<textarea
className="w-full resize-none bg-slate-100 text-slate-800 border p-2 text-[10px] break-all h-full outline-none font-mono"
value={request.verification?.recv}
value={request?.verification?.recv}
></textarea>
)}
</div>
</div>
);
};
}
function TabLabel(props: {
children: ReactNode;
@@ -74,7 +74,8 @@ function TabLabel(props: {
<button
className={c('px-1 select-none cursor-pointer font-bold', {
'text-slate-800 border-b-2 border-green-500': props.active,
'text-slate-400 border-b-2 border-transparent hover:text-slate-500': !props.active,
'text-slate-400 border-b-2 border-transparent hover:text-slate-500':
!props.active,
})}
onClick={props.onClick}
>

View File

@@ -5,18 +5,10 @@ import React, {
useEffect,
useState,
} from 'react';
import {
BackgroundActiontype,
RequestLog,
} from '../../pages/Background/actionTypes';
import {
notarizeRequest,
useRequest,
} from '../../reducers/requests';
import { notarizeRequest, useRequest } from '../../reducers/requests';
import classNames from 'classnames';
import { useDispatch } from 'react-redux';
import {
Navigate,
Route,
Routes,
useLocation,
@@ -34,44 +26,44 @@ type Props = {
const maxTranscriptSize = 16384;
const authToken = 'a28cae3969369c26c1410f5bded83c3f4f914fbc';
const accessToken =
'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
const csrfToken =
'b73b3488687683372af2ea77486a444ccaa5327bbabad709df1b5161a6b83c8d7ec19106a82cb8dd5f8569632ee95ab4c6dc2abf5ad2ed7fa11b8340fcbe86a8fc00df28db6c4109a807f7cb12dd19da';
const userAgent =
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36';
export default function RequestDetail(props: Props): ReactElement {
const request = useRequest(props.requestId);
const navigate = useNavigate();
const dispatch = useDispatch();
const notarize = useCallback(async () => {
if (!request) return;
const hostname = urlify(request.url)?.hostname;
const notaryUrl = await get(NOTARY_API_LS_KEY);
const websocketProxyUrl = await get(PROXY_API_LS_KEY);
const headers = request
.requestHeaders.reduce((acc, h) => {
if (!(/^(origin|referer|Accept-Language|Accept-EncodingAccept)$|^(sec-|x-twitter-)/i.test(h.name))) {
acc[h.name] = h.value;
}
return acc;
}, { Host: urlify(request.url)?.hostname });
//TODO: for some reason, these needs to be override for twitter to work
headers['Accept-Encoding'] = 'identity';
headers['Connection'] = 'close';
const headers: { [k: string]: string } = request.requestHeaders.reduce(
(acc: any, h) => {
acc[h.name] = h.value;
return acc;
},
{ Host: hostname },
);
dispatch(notarizeRequest({
url: request.url,
method: request.method,
headers,
body: request.body,
maxTranscriptSize,
notaryUrl,
websocketProxyUrl,
}))
//TODO: for some reason, these needs to be override for twitter api to work
if (hostname === 'api.twitter.com') {
headers['Accept-Encoding'] = 'identity';
headers['Connection'] = 'close';
}
dispatch(
// @ts-ignore
notarizeRequest({
url: request.url,
method: request.method,
headers,
body: request.requestBody,
maxTranscriptSize,
notaryUrl,
websocketProxyUrl,
}),
);
navigate(`/history`);
}, [request]);
@@ -102,9 +94,18 @@ export default function RequestDetail(props: Props): ReactElement {
</button>
</div>
<Routes>
<Route path="headers" element={<RequestHeaders requestId={props.requestId} />} />
<Route path="payloads" element={<RequestPayload requestId={props.requestId} />} />
<Route path="response" element={<WebResponse requestId={props.requestId} />} />
<Route
path="headers"
element={<RequestHeaders requestId={props.requestId} />}
/>
<Route
path="payloads"
element={<RequestPayload requestId={props.requestId} />}
/>
<Route
path="response"
element={<WebResponse requestId={props.requestId} />}
/>
<Route path="/" element={<NavigateWithParams to="/headers" />} />
</Routes>
</>

View File

@@ -38,8 +38,8 @@ export type RequestHistory = {
url: string;
method: string;
headers: { [key: string]: string };
body: string;
maxTranscriptSize: string;
body?: string;
maxTranscriptSize: number;
notaryUrl: string;
websocketProxyUrl: string;
status: '' | 'pending' | 'success' | 'error';

View File

@@ -9,7 +9,7 @@ import NodeCache from 'node-cache';
import { addRequest } from '../../reducers/requests';
import { addRequestHistory } from '../../reducers/history';
import { Level } from 'level';
import charwise from 'charwise';
const charwise = require('charwise');
let RequestsLogs: {
[tabId: string]: NodeCache;
@@ -38,6 +38,7 @@ chrome.tabs.onRemoved.addListener((tab) => {
(async () => {
const offscreenUrl = chrome.runtime.getURL('offscreen.html');
// @ts-ignore
const existingContexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
documentUrls: [offscreenUrl],
@@ -224,7 +225,7 @@ chrome.tabs.onRemoved.addListener((tab) => {
if (error) {
const newReq = await setNotaryRequestError(id, error);
if (!newReq) return;
chrome.runtime.sendMessage({
type: BackgroundActiontype.push_action,
data: {
@@ -237,7 +238,7 @@ chrome.tabs.onRemoved.addListener((tab) => {
if (verification) {
const newReq = await setNotaryRequestVerification(id, verification);
if (!newReq) return;
chrome.runtime.sendMessage({
type: BackgroundActiontype.push_action,
data: {
@@ -329,16 +330,19 @@ chrome.tabs.onRemoved.addListener((tab) => {
const db = new Level('./ext-db', {
valueEncoding: 'json',
});
const historyDb = db.sublevel('history', { valueEncoding: 'json' });
const historyDb = db.sublevel<string, RequestHistory>('history', {
valueEncoding: 'json',
});
async function addNotaryRequest(
now = Date.now(),
request: RequestHistory,
request: Omit<RequestHistory, 'status' | 'id'>,
): Promise<RequestHistory> {
const id = charwise.encode(now).toString('hex');
const newReq = {
const newReq: RequestHistory = {
...request,
id,
status: '',
};
await historyDb.put(id, newReq);
return newReq;
@@ -352,7 +356,7 @@ async function addNotaryRequestProofs(
if (!existing) return null;
const newReq = {
const newReq: RequestHistory = {
...existing,
proof,
status: 'success',
@@ -389,7 +393,7 @@ async function setNotaryRequestError(
if (!existing) return null;
const newReq = {
const newReq: RequestHistory = {
...existing,
error,
status: 'error',

View File

@@ -49,13 +49,13 @@ class TLSN {
await this.waitForStart();
console.log('worker', url, {
...options,
notaryUrl: options.notaryUrl,
websocketProxyUrl: options.websocketProxyUrl,
notaryUrl: options?.notaryUrl,
websocketProxyUrl: options?.websocketProxyUrl,
});
const resProver = await prover(url, {
...options,
notaryUrl: options.notaryUrl,
websocketProxyUrl: options.websocketProxyUrl,
notaryUrl: options?.notaryUrl,
websocketProxyUrl: options?.websocketProxyUrl,
});
const resJSON = JSON.parse(resProver);
devlog('!@# resProver,resJSON=', { resProver, resJSON });

View File

@@ -30,18 +30,18 @@ export default function RequestBuilder(props?: {
const loc = useLocation();
const navigate = useNavigate();
const subpath = props.subpath || '/custom';
const [_url, setUrl] = useState(props.url || '');
const subpath = props?.subpath || '/custom';
const [_url, setUrl] = useState(props?.url || '');
const [params, setParams] = useState<[string, string, boolean?][]>(
props.params || [],
props?.params || [],
);
const [headers, setHeaders] = useState<[string, string, boolean?][]>(
props.headers || [],
props?.headers || [],
);
const [body, setBody] = useState<string | undefined>(props.body);
const [method, setMethod] = useState<string>(props.method || 'GET');
const [body, setBody] = useState<string | undefined>(props?.body);
const [method, setMethod] = useState<string>(props?.method || 'GET');
const [response, setResponse] = useState<Response | null>(
props.response || null,
props?.response || null,
);
const url = urlify(_url);

View File

@@ -1,14 +1,11 @@
import React, { ReactElement } from 'react';
import RequestDetail from '../../components/RequestDetail';
import { useParams } from 'react-router';
import { useRequest } from '../../reducers/requests';
export default function Request(): ReactElement {
const params = useParams<{ requestId: string }>();
return (
<>
<RequestDetail requestId={params.requestId} />
</>
<>{!!params.requestId && <RequestDetail requestId={params.requestId} />}</>
);
}

View File

@@ -30,7 +30,7 @@ const initialState: State = {
order: [],
};
export const addRequestHistory = (request: RequestHistory) => {
export const addRequestHistory = (request?: RequestHistory | null) => {
return {
type: ActionType['/history/addRequest'],
payload: request,
@@ -56,6 +56,9 @@ export default function history(
switch (action.type) {
case ActionType['/history/addRequest']: {
const payload: RequestHistory = action.payload;
if (!payload) return state;
const existing = state.map[payload.id];
const newMap = {
...state.map,
@@ -91,8 +94,9 @@ export const useHistoryOrder = (): string[] => {
}, deepEqual);
};
export const useRequestHistory = (id: string): RequestHistory | undefined => {
export const useRequestHistory = (id?: string): RequestHistory | undefined => {
return useSelector((state: AppRootState) => {
if (!id) return undefined;
return state.history.map[id];
}, deepEqual);
};

View File

@@ -1,4 +1,7 @@
import { type RequestLog, type RequestHistory } from '../pages/Background/actionTypes';
import {
type RequestLog,
type RequestHistory,
} from '../pages/Background/actionTypes';
import { useSelector } from 'react-redux';
import { AppRootState } from './index';
import deepEqual from 'fast-deep-equal';
@@ -36,22 +39,10 @@ export const setRequests = (requests: RequestLog[]): Action<RequestLog[]> => ({
});
export const notarizeRequest = (options: RequestHistory) => async () => {
const notaryUrl = await get(NOTARY_API_LS_KEY);
const websocketProxyUrl = await get(PROXY_API_LS_KEY);
console.log({
type: BackgroundActiontype.prove_request_start,
data: {
url: options.url,
method: options.method,
headers: options.headers,
body: options.body,
maxTranscriptSize: options.maxTranscriptSize,
notaryUrl,
websocketProxyUrl,
},
})
const notaryUrl = await get(NOTARY_API_LS_KEY, 'https://127.0.0.1:7047');
const websocketProxyUrl = await get(PROXY_API_LS_KEY, 'ws://127.0.0.1:55688');
console.log({ notaryUrl, websocketProxyUrl });
chrome.runtime.sendMessage<any, string>({
type: BackgroundActiontype.prove_request_start,
data: {
@@ -64,7 +55,7 @@ export const notarizeRequest = (options: RequestHistory) => async () => {
websocketProxyUrl,
},
});
}
};
export const setActiveTab = (
activeTab: chrome.tabs.Tab | null,

View File

@@ -17,15 +17,18 @@ export function urlify(
}
}
export function devlog(text: string) {
export function devlog(...args: any[]) {
if (process.env.NODE_ENV === 'development') {
console.log(text);
console.log(...args);
}
}
export function download(filename: string, content: string) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
const element = document.createElement('a');
element.setAttribute(
'href',
'data:text/plain;charset=utf-8,' + encodeURIComponent(content),
);
element.setAttribute('download', filename);
element.style.display = 'none';

View File

@@ -6,9 +6,9 @@ export async function set(key: string, value: string) {
return chrome.storage.sync.set({ [key]: value });
}
export async function get(key: string) {
export async function get(key: string, defaultValue?: string) {
return chrome.storage.sync
.get(key)
.then((json: any) => json[key])
.then((json: any) => json[key] || defaultValue)
.catch(() => '');
}