From bbfdb139c6822b8a6477549a75c7bd3a299acf0f Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Thu, 20 Jul 2023 08:57:58 +0700 Subject: [PATCH] update stronghold --- package.json | 2 +- pnpm-lock.yaml | 28 ++++++++++++++-------------- src-tauri/src/main.rs | 4 ++-- src/app/auth/create/step-2.tsx | 10 ++-------- src/app/auth/create/step-5.tsx | 2 +- src/app/auth/import/step-2.tsx | 14 ++++---------- src/app/auth/migrate.tsx | 8 +------- src/app/auth/onboarding.tsx | 24 ++++++++++-------------- src/app/auth/unlock.tsx | 8 +------- src/app/root.tsx | 25 +++++++++++-------------- src/app/space/hooks/useNewsfeed.tsx | 7 ++++--- src/shared/protected.tsx | 4 ++-- src/stores/onboarding.tsx | 9 --------- src/stores/stronghold.tsx | 27 +++++++++++++++------------ src/utils/hooks/usePublish.tsx | 11 ++--------- src/utils/hooks/useSecureStorage.tsx | 18 ++++-------------- 16 files changed, 74 insertions(+), 127 deletions(-) diff --git a/package.json b/package.json index 5d0ef46b..034b2fff 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "cheerio": "1.0.0-rc.12", "dayjs": "^1.11.9", "destr": "^1.2.2", - "framer-motion": "^10.12.22", + "framer-motion": "^10.13.0", "get-urls": "^11.0.0", "immer": "^10.0.2", "light-bolt11-decoder": "^3.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c455ed35..6ca71662 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,8 +38,8 @@ dependencies: specifier: ^1.2.2 version: 1.2.2 framer-motion: - specifier: ^10.12.22 - version: 10.12.22(react-dom@18.2.0)(react@18.2.0) + specifier: ^10.13.0 + version: 10.13.0(react-dom@18.2.0)(react@18.2.0) get-urls: specifier: ^11.0.0 version: 11.0.0 @@ -2210,7 +2210,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001516 + caniuse-lite: 1.0.30001517 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -2272,8 +2272,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001516 - electron-to-chromium: 1.4.464 + caniuse-lite: 1.0.30001517 + electron-to-chromium: 1.4.465 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true @@ -2333,8 +2333,8 @@ packages: engines: {node: '>=6'} dev: false - /caniuse-lite@1.0.30001516: - resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==} + /caniuse-lite@1.0.30001517: + resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==} dev: true /ccount@2.0.1: @@ -2735,8 +2735,8 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - /electron-to-chromium@1.4.464: - resolution: {integrity: sha512-guZ84yoou4+ILNdj0XEbmGs6DEWj6zpVOWYpY09GU66yEb0DSYvP/biBPzHn0GuW/3RC/pnaYNUWlQE1fJYtgA==} + /electron-to-chromium@1.4.465: + resolution: {integrity: sha512-XQcuHvEJRMU97UJ75e170mgcITZoz0lIyiaVjk6R+NMTJ8KBIvUHYd1779swgOppUlzxR+JsLpq59PumaXS1jQ==} dev: true /emoji-regex@8.0.0: @@ -3327,8 +3327,8 @@ packages: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true - /framer-motion@10.12.22(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-bBGYPOxvxcfzS7/py9MEqDucmXBkVl2g42HNlXXPieSTSGGkr8L7+MilCnrU6uX3HrNk/tcB++1SkWE8BosHFw==} + /framer-motion@10.13.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-xKhw9VCizmwEHbopOfluaoVunGHSZyMztGbTvsgOYqCjaKu6qtlwWY1J+6GhL41NY1P157JgEikjDm67XCFnvQ==} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 @@ -6025,8 +6025,8 @@ packages: inline-style-parser: 0.1.1 dev: false - /sucrase@3.33.0: - resolution: {integrity: sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==} + /sucrase@3.34.0: + resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} engines: {node: '>=8'} hasBin: true dependencies: @@ -6100,7 +6100,7 @@ packages: postcss-nested: 6.0.1(postcss@8.4.26) postcss-selector-parser: 6.0.13 resolve: 1.22.2 - sucrase: 3.33.0 + sucrase: 3.34.0 transitivePeerDependencies: - ts-node dev: true diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index b1ce70de..a1487dd9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -121,8 +121,8 @@ fn main() { tauri_plugin_stronghold::Builder::new(|password| { let config = argon2::Config { lanes: 2, - mem_cost: 50_000, - time_cost: 30, + mem_cost: 10_000, + time_cost: 10, thread_mode: argon2::ThreadMode::from_threads(2), variant: argon2::Variant::Argon2id, ..Default::default() diff --git a/src/app/auth/create/step-2.tsx b/src/app/auth/create/step-2.tsx index 19388650..dd915c96 100644 --- a/src/app/auth/create/step-2.tsx +++ b/src/app/auth/create/step-2.tsx @@ -32,12 +32,9 @@ export function CreateStep2Screen() { const [passwordInput, setPasswordInput] = useState('password'); const [loading, setLoading] = useState(false); - const [privkey, setPassword] = useStronghold((state) => [ - state.privkey, - state.setPassword, - ]); - const pubkey = useOnboarding((state) => state.privkey); + const privkey = useStronghold((state) => state.privkey); + const pubkey = useOnboarding((state) => state.pubkey); const { save } = useSecureStorage(); @@ -60,9 +57,6 @@ export function CreateStep2Screen() { const onSubmit = async (data: { [x: string]: string }) => { setLoading(true); if (data.password.length > 3) { - // add password to local state - setPassword(data.password); - // save privkey to secure storage await save(pubkey, privkey, data.password); diff --git a/src/app/auth/create/step-5.tsx b/src/app/auth/create/step-5.tsx index fd86eeff..28f75dfa 100644 --- a/src/app/auth/create/step-5.tsx +++ b/src/app/auth/create/step-5.tsx @@ -137,7 +137,7 @@ export function CreateStep5Screen() { }; const update = useMutation({ - mutationFn: (follows: any) => { + mutationFn: (follows: string[]) => { return updateAccount('follows', follows, account.pubkey); }, onSuccess: () => { diff --git a/src/app/auth/import/step-2.tsx b/src/app/auth/import/step-2.tsx index 3d5cd54c..5dfab3cc 100644 --- a/src/app/auth/import/step-2.tsx +++ b/src/app/auth/import/step-2.tsx @@ -32,11 +32,8 @@ export function ImportStep2Screen() { const [passwordInput, setPasswordInput] = useState('password'); const [loading, setLoading] = useState(false); - const [privkey, setPassword] = useStronghold((state) => [ - state.privkey, - state.setPassword, - ]); + const privkey = useStronghold((state) => state.privkey); const pubkey = useOnboarding((state) => state.pubkey); const { save } = useSecureStorage(); @@ -60,9 +57,6 @@ export function ImportStep2Screen() { const onSubmit = async (data: { [x: string]: string }) => { setLoading(true); if (data.password.length > 3) { - // add password to local state - setPassword(data.password); - // save privkey to secure storage await save(pubkey, privkey, data.password); @@ -115,9 +109,9 @@ export function ImportStep2Screen() {

- Password is use to secure your key store in local machine, when you move - to other clients, you just need to copy your private key as nsec or - hexstring + Password is use to unlock app and secure your key store in local machine. + When you move to other clients, you just need to copy your private key as + nsec or hexstring

diff --git a/src/app/auth/migrate.tsx b/src/app/auth/migrate.tsx index ed174eee..034f90c3 100644 --- a/src/app/auth/migrate.tsx +++ b/src/app/auth/migrate.tsx @@ -33,13 +33,10 @@ const resolver: Resolver = async (values) => { export function MigrateScreen() { const queryClient = useQueryClient(); const navigate = useNavigate(); + const setPrivkey = useStronghold((state) => state.setPrivkey); const [passwordInput, setPasswordInput] = useState('password'); const [loading, setLoading] = useState(false); - const [setPassword, setPrivkey] = useStronghold((state) => [ - state.setPassword, - state.setPrivkey, - ]); const { account } = useAccount(); const { save } = useSecureStorage(); @@ -63,9 +60,6 @@ export function MigrateScreen() { const onSubmit = async (data: { [x: string]: string }) => { setLoading(true); if (data.password.length > 3) { - // add password to local state - setPassword(data.password); - // load private in secure storage try { // save privkey to secure storage diff --git a/src/app/auth/onboarding.tsx b/src/app/auth/onboarding.tsx index b0fa56db..1da80940 100644 --- a/src/app/auth/onboarding.tsx +++ b/src/app/auth/onboarding.tsx @@ -21,8 +21,7 @@ export function OnboardingScreen() { // publish event publish({ - content: - 'Running Lume, fighting for better future, join us here: https://lume.nu', + content: 'Running Lume, join with me: https://lume.nu', kind: 1, tags: [], }); @@ -55,18 +54,15 @@ export function OnboardingScreen() { )}
-

Running Lume, fighting for better future

-

- join us here:{' '} - - https://lume.nu - -

+

Running Lume, join with me

+ + https://lume.nu +
diff --git a/src/app/auth/unlock.tsx b/src/app/auth/unlock.tsx index 5c65b33b..914a4fe5 100644 --- a/src/app/auth/unlock.tsx +++ b/src/app/auth/unlock.tsx @@ -29,13 +29,10 @@ const resolver: Resolver = async (values) => { export function UnlockScreen() { const navigate = useNavigate(); + const setPrivkey = useStronghold((state) => state.setPrivkey); const [passwordInput, setPasswordInput] = useState('password'); const [loading, setLoading] = useState(false); - const [setPrivkey, setPassword] = useStronghold((state) => [ - state.setPrivkey, - state.setPassword, - ]); const { account } = useAccount(); const { load } = useSecureStorage(); @@ -59,9 +56,6 @@ export function UnlockScreen() { const onSubmit = async (data: { [x: string]: string }) => { setLoading(true); if (data.password.length > 3) { - // add password to local state - setPassword(data.password); - // load private in secure storage try { const privkey = await load(account.pubkey, data.password); diff --git a/src/app/root.tsx b/src/app/root.tsx index 81aab4f6..dc389bf9 100644 --- a/src/app/root.tsx +++ b/src/app/root.tsx @@ -13,7 +13,7 @@ import { updateLastLogin, } from '@libs/storage'; -import { LoaderIcon, LumeIcon } from '@shared/icons'; +import { LoaderIcon } from '@shared/icons'; import { nHoursAgo } from '@utils/date'; import { useAccount } from '@utils/hooks/useAccount'; @@ -175,27 +175,24 @@ export function Root() { }, [status]); return ( -
-
+
+
-
-
- +
+
+
-

- Here's an interesting fact: +

+ Prefetching data...

-

- Bitcoin and Nostr can be used by anyone, and no one can stop you! +

+ This may take a few seconds, please don't close app.

-
- -
diff --git a/src/app/space/hooks/useNewsfeed.tsx b/src/app/space/hooks/useNewsfeed.tsx index e95918b7..40209e73 100644 --- a/src/app/space/hooks/useNewsfeed.tsx +++ b/src/app/space/hooks/useNewsfeed.tsx @@ -19,7 +19,7 @@ export function useNewsfeed() { useEffect(() => { if (status === 'success' && account) { - const follows = account ? JSON.parse(account.follows) : []; + const follows = account ? JSON.parse(account.follows as string) : []; const filter: NDKFilter = { kinds: [1, 6], @@ -30,7 +30,6 @@ export function useNewsfeed() { sub.current = ndk.subscribe(filter, { closeOnEose: false }); sub.current.addListener('event', (event: NDKEvent) => { - console.log('new note: ', event); // add to db createNote( event.id, @@ -46,7 +45,9 @@ export function useNewsfeed() { } return () => { - sub.current.stop(); + if (sub.current) { + sub.current.stop(); + } }; }, [status]); } diff --git a/src/shared/protected.tsx b/src/shared/protected.tsx index 9f9f7576..dec04391 100644 --- a/src/shared/protected.tsx +++ b/src/shared/protected.tsx @@ -6,7 +6,7 @@ import { useStronghold } from '@stores/stronghold'; import { useAccount } from '@utils/hooks/useAccount'; export function Protected({ children }: { children: ReactNode }) { - const password = useStronghold((state) => state.password); + const privkey = useStronghold((state) => state.privkey); const { status, account } = useAccount(); if (status === 'success' && !account) { @@ -17,7 +17,7 @@ export function Protected({ children }: { children: ReactNode }) { return ; } - if (status === 'success' && account && !password) { + if (status === 'success' && account && !privkey) { return ; } diff --git a/src/stores/onboarding.tsx b/src/stores/onboarding.tsx index 562336ad..cd8644cf 100644 --- a/src/stores/onboarding.tsx +++ b/src/stores/onboarding.tsx @@ -3,11 +3,8 @@ import { create } from 'zustand'; interface OnboardingState { profile: { [x: string]: string }; pubkey: string; - privkey: string; createProfile: (data: { [x: string]: string }) => void; setPubkey: (pubkey: string) => void; - setPrivkey: (privkey: string) => void; - clearPrivkey: (privkey: string) => void; } export const useOnboarding = create((set) => ({ @@ -20,10 +17,4 @@ export const useOnboarding = create((set) => ({ setPubkey: (pubkey: string) => { set({ pubkey: pubkey }); }, - setPrivkey: (privkey: string) => { - set({ privkey: privkey }); - }, - clearPrivkey: () => { - set({ privkey: '' }); - }, })); diff --git a/src/stores/stronghold.tsx b/src/stores/stronghold.tsx index 90823596..db8ddd55 100644 --- a/src/stores/stronghold.tsx +++ b/src/stores/stronghold.tsx @@ -1,19 +1,22 @@ import { create } from 'zustand'; +import { createJSONStorage, persist } from 'zustand/middleware'; interface StrongholdState { - password: null | string; privkey: null | string; - setPassword: (password: string) => void; setPrivkey: (privkey: string) => void; } -export const useStronghold = create((set) => ({ - password: null, - privkey: null, - setPassword: (password: string) => { - set({ password: password }); - }, - setPrivkey: (privkey: string) => { - set({ privkey: privkey }); - }, -})); +export const useStronghold = create()( + persist( + (set) => ({ + privkey: null, + setPrivkey: (privkey: string) => { + set({ privkey: privkey }); + }, + }), + { + name: 'stronghold', + storage: createJSONStorage(() => sessionStorage), + } + ) +); diff --git a/src/utils/hooks/usePublish.tsx b/src/utils/hooks/usePublish.tsx index c37d20e2..ebbe1cee 100644 --- a/src/utils/hooks/usePublish.tsx +++ b/src/utils/hooks/usePublish.tsx @@ -5,14 +5,12 @@ import { useNDK } from '@libs/ndk/provider'; import { useStronghold } from '@stores/stronghold'; import { useAccount } from '@utils/hooks/useAccount'; -import { useSecureStorage } from '@utils/hooks/useSecureStorage'; export function usePublish() { const { ndk } = useNDK(); const { account } = useAccount(); - const { load } = useSecureStorage(); - const cachePrivkey = useStronghold((state) => state.privkey); + const privkey = useStronghold((state) => state.privkey); const publish = async ({ content, @@ -23,12 +21,7 @@ export function usePublish() { kind: NDKKind | number; tags: string[][]; }): Promise => { - let privkey: string; - if (cachePrivkey) { - privkey = cachePrivkey; - } else { - privkey = await load(account.pubkey); - } + if (!privkey) throw new Error('Private key not found'); const event = new NDKEvent(ndk); const signer = new NDKPrivateKeySigner(privkey); diff --git a/src/utils/hooks/useSecureStorage.tsx b/src/utils/hooks/useSecureStorage.tsx index a5b13548..3b2b3282 100644 --- a/src/utils/hooks/useSecureStorage.tsx +++ b/src/utils/hooks/useSecureStorage.tsx @@ -1,13 +1,9 @@ import { appConfigDir } from '@tauri-apps/api/path'; import { Stronghold } from 'tauri-plugin-stronghold-api'; -import { useStronghold } from '@stores/stronghold'; - const dir = await appConfigDir(); export function useSecureStorage() { - const password = useStronghold((state) => state.password); - async function getClient(stronghold: Stronghold) { try { return await stronghold.loadClient('lume'); @@ -16,22 +12,16 @@ export function useSecureStorage() { } } - const save = async (key: string, value: string, userpass?: string) => { - const stronghold = await Stronghold.load( - `${dir}lume.stronghold`, - userpass ? userpass : password - ); + const save = async (key: string, value: string, password: string) => { + const stronghold = await Stronghold.load(`${dir}lume.stronghold`, password); const client = await getClient(stronghold); const store = client.getStore(); await store.insert(key, Array.from(new TextEncoder().encode(value))); return await stronghold.save(); }; - const load = async (key: string, userpass?: string) => { - const stronghold = await Stronghold.load( - `${dir}lume.stronghold`, - userpass ? userpass : password - ); + const load = async (key: string, password: string) => { + const stronghold = await Stronghold.load(`${dir}lume.stronghold`, password); const client = await getClient(stronghold); const store = client.getStore(); const value = await store.get(key);