From eeb348b3560cf7e8595d782d1acb209e3174f96d Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 10:09:41 -0800 Subject: [PATCH 01/18] Feat: first pass at recoverFileSystem --- src/filesystem.ts | 70 +++++++++++++++++++++++++++++++++++++++++- src/fs/types/params.ts | 5 +++ src/index.ts | 21 ++++++++++--- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 src/fs/types/params.ts diff --git a/src/filesystem.ts b/src/filesystem.ts index 98023b78f..c0716e024 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -1,3 +1,4 @@ +import * as uint8arrays from "uint8arrays" import { CID } from "multiformats/cid" import * as Depot from "./components/depot/implementation.js" @@ -8,10 +9,17 @@ import * as Versions from "./fs/versions.js" import FileSystem, { Dependencies } from "./fs/filesystem.js" +import * as Ucan from "./ucan/index.js" + +import * as RootKey from "./common/root-key" + import { Branch } from "./path/index.js" import { Configuration } from "./configuration.js" import { Maybe, decodeCID, EMPTY_CID } from "./common/index.js" +import { type RecoverFileSystemParams } from "./fs/types/params" +import { AuthenticationStrategy } from "./index.js" + /** * Load a user's file system. @@ -105,6 +113,66 @@ export async function loadFileSystem({ config, dependencies, rootKey, username } return fs } +/** + * Recover a user's file system. + */ +export async function recoverFileSystem({ + agentDID, + auth, + dependencies, + oldUsername, + newUsername, + readKey, +}: { + agentDID: () => Promise + auth: AuthenticationStrategy + dependencies: Dependencies +} & RecoverFileSystemParams): Promise<{ success: boolean }> { + const { crypto, reference, storage } = dependencies + + const newRootDID = await agentDID() + + // Register a new user with the `newUsername` + const { success } = await auth.register({ + username: newUsername, + }) + if (!success) { + throw new Error("Failed to register new user") + } + + // Build an ephemeral UCAN to authorize the dataRoot.update call + const proof: string | null = await storage.getItem(storage.KEYS.ACCOUNT_UCAN) + const ucan = await Ucan.build({ + dependencies, + potency: "APPEND", + resource: "*", + proof: proof ? proof : undefined, + lifetimeInSeconds: 60 * 3, // Three minutes + audience: newRootDID, + issuer: newRootDID, + }) + + const oldRootCID = await reference.dataRoot.lookup(oldUsername) + if (!oldRootCID) { + return { + success: false + } + } + + // Update the dataRoot of the new user + await reference.dataRoot.update(oldRootCID, ucan) + + // Store the accountDID, which is used to namespace the readKey + await RootKey.store({ + accountDID: newRootDID, + crypto: crypto, + readKey, + }) + + return { + success: true + } +} // VERSIONING @@ -209,4 +277,4 @@ async function getDataRoot( resolve(dataCid?.toString() === EMPTY_CID ? null : dataCid) }, retryInterval) }) -} \ No newline at end of file +} diff --git a/src/fs/types/params.ts b/src/fs/types/params.ts new file mode 100644 index 000000000..97754ef41 --- /dev/null +++ b/src/fs/types/params.ts @@ -0,0 +1,5 @@ +export type RecoverFileSystemParams = { + newUsername: string + oldUsername: string + readKey: Uint8Array +} diff --git a/src/index.ts b/src/index.ts index 3c444bf11..48c6adc0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,12 +49,19 @@ import { Components } from "./components.js" import { Configuration, namespace } from "./configuration.js" import { isString, Maybe } from "./common/index.js" import { Session } from "./session.js" -import { loadFileSystem } from "./filesystem.js" +import { loadFileSystem, recoverFileSystem } from "./filesystem.js" import FileSystem from "./fs/filesystem.js" +// TYPES + + +import { type RecoverFileSystemParams } from "./fs/types/params" + + // IMPLEMENTATIONS + import * as BaseAuth from "./components/auth/implementation/base.js" import * as BaseReference from "./components/reference/implementation/base.js" import * as BrowserCrypto from "./components/crypto/implementation/browser.js" @@ -143,9 +150,13 @@ export enum ProgramError { UnsupportedBrowser = "UNSUPPORTED_BROWSER" } - export type ShortHands = { loadFileSystem: (username: string) => Promise + recoverFileSystem: ({ + newUsername, + oldUsername, + readKey, + }: RecoverFileSystemParams) => Promise<{ success: boolean }> agentDID: () => Promise sharingDID: () => Promise } @@ -485,8 +496,10 @@ export async function assemble(config: Configuration, components: Components): P // Shorthands const shorthands: ShortHands = { - loadFileSystem: (username: string) => loadFileSystem({ config, username, dependencies: components }), - + loadFileSystem: (username: string) => + loadFileSystem({ config, username, dependencies: components }), + recoverFileSystem: (params: RecoverFileSystemParams) => + recoverFileSystem({ agentDID: () => DID.agent(components.crypto), auth, dependencies: components, ...params }), agentDID: () => DID.agent(components.crypto), sharingDID: () => DID.sharing(components.crypto), } From b3441d82f6898713aebf01f2433fbe8f238be0b2 Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 10:37:19 -0800 Subject: [PATCH 02/18] Chore: add try catch to handle all errors --- src/filesystem.ts | 76 +++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index c0716e024..4e16c5cdb 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -128,49 +128,53 @@ export async function recoverFileSystem({ auth: AuthenticationStrategy dependencies: Dependencies } & RecoverFileSystemParams): Promise<{ success: boolean }> { - const { crypto, reference, storage } = dependencies + try { + const { crypto, reference, storage } = dependencies - const newRootDID = await agentDID() + const newRootDID = await agentDID() - // Register a new user with the `newUsername` - const { success } = await auth.register({ - username: newUsername, - }) - if (!success) { - throw new Error("Failed to register new user") - } - - // Build an ephemeral UCAN to authorize the dataRoot.update call - const proof: string | null = await storage.getItem(storage.KEYS.ACCOUNT_UCAN) - const ucan = await Ucan.build({ - dependencies, - potency: "APPEND", - resource: "*", - proof: proof ? proof : undefined, - lifetimeInSeconds: 60 * 3, // Three minutes - audience: newRootDID, - issuer: newRootDID, - }) + // Register a new user with the `newUsername` + const { success } = await auth.register({ + username: newUsername, + }) + if (!success) { + throw new Error("Failed to register new user") + } - const oldRootCID = await reference.dataRoot.lookup(oldUsername) - if (!oldRootCID) { - return { - success: false + // Build an ephemeral UCAN to authorize the dataRoot.update call + const proof: string | null = await storage.getItem(storage.KEYS.ACCOUNT_UCAN) + const ucan = await Ucan.build({ + dependencies, + potency: "APPEND", + resource: "*", + proof: proof ? proof : undefined, + lifetimeInSeconds: 60 * 3, // Three minutes + audience: newRootDID, + issuer: newRootDID, + }) + + const oldRootCID = await reference.dataRoot.lookup(oldUsername) + if (!oldRootCID) { + throw new Error("Failed to lookup oldUsername") } - } - // Update the dataRoot of the new user - await reference.dataRoot.update(oldRootCID, ucan) + // Update the dataRoot of the new user + await reference.dataRoot.update(oldRootCID, ucan) - // Store the accountDID, which is used to namespace the readKey - await RootKey.store({ - accountDID: newRootDID, - crypto: crypto, - readKey, - }) + // Store the accountDID, which is used to namespace the readKey + await RootKey.store({ + accountDID: newRootDID, + crypto: crypto, + readKey, + }) - return { - success: true + return { + success: true + } + } catch (error) { + return { + success: false + } } } From 4efaea11cec90451d7659f6d788c5f99c637714b Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 11:08:24 -0800 Subject: [PATCH 03/18] Fix: add line break and remove unused import --- src/filesystem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 4e16c5cdb..781bf56a6 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -1,4 +1,3 @@ -import * as uint8arrays from "uint8arrays" import { CID } from "multiformats/cid" import * as Depot from "./components/depot/implementation.js" @@ -18,6 +17,7 @@ import { Configuration } from "./configuration.js" import { Maybe, decodeCID, EMPTY_CID } from "./common/index.js" import { type RecoverFileSystemParams } from "./fs/types/params" + import { AuthenticationStrategy } from "./index.js" From 616c809ed3eabfe59959bfc682840474e35d3d43 Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 11:19:09 -0800 Subject: [PATCH 04/18] Chore: update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca52f5fd1..0ad584a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### v0.35.2 +Adds `program.recoverFileSystem({ newUsername, oldUsername, readKey })` shorthand method so apps will no longer have to implement the FS recovery flow manually. + +### v0.35.2 + Fixes issue with the types of the `path.appData` function. Now has the correct overloads. ### v0.35.1 @@ -354,7 +358,7 @@ Upgrade to CIDv1. }); ``` -- Those prerequisites are passed to the `wn.redirectToLobby` function. +- Those prerequisites are passed to the `wn.redirectToLobby` function. (So the auth lobby has the correct parameters to determine the permissions to ask the user) - Adds the ability to use multiple apps with one file system (closes #73) - The SDK now handles multiple UCANs From c492c115afbdc01b6ee7545bbb292f0bfe540ce5 Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 15:00:14 -0800 Subject: [PATCH 05/18] Fix: changelog release number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ad584a62..8085b9cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### v0.35.2 +### v0.35.3 Adds `program.recoverFileSystem({ newUsername, oldUsername, readKey })` shorthand method so apps will no longer have to implement the FS recovery flow manually. From e1129b3156c8cc1373f036054b71eae595241847 Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 15:03:17 -0800 Subject: [PATCH 06/18] Fix: import for tests --- src/filesystem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 781bf56a6..2dcecc21f 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -10,7 +10,7 @@ import FileSystem, { Dependencies } from "./fs/filesystem.js" import * as Ucan from "./ucan/index.js" -import * as RootKey from "./common/root-key" +import * as RootKey from "./common/root-key.js" import { Branch } from "./path/index.js" import { Configuration } from "./configuration.js" From ce17dcaa5ca2476adb893a2ef295cc8f4a46bafb Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 15:10:09 -0800 Subject: [PATCH 07/18] Chore: dry up agentDID usage --- src/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 48c6adc0a..53360e8c6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -494,13 +494,16 @@ export async function assemble(config: Configuration, components: Components): P } + // AgentDID + const agentDID = async () => DID.agent(components.crypto) + // Shorthands const shorthands: ShortHands = { loadFileSystem: (username: string) => loadFileSystem({ config, username, dependencies: components }), recoverFileSystem: (params: RecoverFileSystemParams) => - recoverFileSystem({ agentDID: () => DID.agent(components.crypto), auth, dependencies: components, ...params }), - agentDID: () => DID.agent(components.crypto), + recoverFileSystem({ agentDID, auth, dependencies: components, ...params }), + agentDID, sharingDID: () => DID.sharing(components.crypto), } From 0c10c3c1d52d9c2513068e21ad6df5da7a69676e Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 15:11:09 -0800 Subject: [PATCH 08/18] Fix: remove async --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 53360e8c6..b8e09a482 100644 --- a/src/index.ts +++ b/src/index.ts @@ -495,7 +495,7 @@ export async function assemble(config: Configuration, components: Components): P } // AgentDID - const agentDID = async () => DID.agent(components.crypto) + const agentDID = () => DID.agent(components.crypto) // Shorthands const shorthands: ShortHands = { From e0dc84ee80e112878648c4e1426be67db4bad3dd Mon Sep 17 00:00:00 2001 From: avivash Date: Thu, 12 Jan 2023 15:31:16 -0800 Subject: [PATCH 09/18] Chore: update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c68310b41..a8f700d26 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ __Notes:__ - You can use alternative authentication strategies, such as [webnative-walletauth](https://github.com/fission-codes/webnative-walletauth). - You can remove all traces of the user using `await session.destroy()` - You can load the file system separately if you're using a web worker. This is done using the combination of `configuration.fileSystem.loadImmediately = false` and `program.loadFileSystem()` +- You can recover a file system if you've downloaded a Recovery Kit by calling `program.recoverFileSystem({ newUsername, oldUsername, readKey })`. The `oldUsername` and `readKey` can be parsed from the uploaded Recovery Kit and the `newUsername` can be generated before calling the function. Please refer to [this example](https://github.com/webnative-examples/webnative-app-template/blob/5498e7062a4578028b8b55d2ac4c611bd5daab85/src/components/auth/recover/HasRecoveryKit.svelte#L49) from Fission's Webnative App Template ## Working with the file system From 7cdcb341f53bd9d9f2dc6bd55f41ee8b976dc72f Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 07:54:30 -0800 Subject: [PATCH 10/18] Fix: add missing .js extensions to imports --- src/filesystem.ts | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 2dcecc21f..209c6da66 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -16,7 +16,7 @@ import { Branch } from "./path/index.js" import { Configuration } from "./configuration.js" import { Maybe, decodeCID, EMPTY_CID } from "./common/index.js" -import { type RecoverFileSystemParams } from "./fs/types/params" +import { type RecoverFileSystemParams } from "./fs/types/params.js" import { AuthenticationStrategy } from "./index.js" diff --git a/src/index.ts b/src/index.ts index b8e09a482..63762488d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -56,7 +56,7 @@ import FileSystem from "./fs/filesystem.js" // TYPES -import { type RecoverFileSystemParams } from "./fs/types/params" +import { type RecoverFileSystemParams } from "./fs/types/params.js" // IMPLEMENTATIONS From c2bf043ebbb8fe1fea59768717536b6a6b84be62 Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 07:56:16 -0800 Subject: [PATCH 11/18] Fix: update comment --- src/filesystem.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 209c6da66..06c2a5aec 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -142,7 +142,9 @@ export async function recoverFileSystem({ } // Build an ephemeral UCAN to authorize the dataRoot.update call - const proof: string | null = await storage.getItem(storage.KEYS.ACCOUNT_UCAN) + const proof: string | null = await storage.getItem( + storage.KEYS.ACCOUNT_UCAN + ) const ucan = await Ucan.build({ dependencies, potency: "APPEND", @@ -161,7 +163,7 @@ export async function recoverFileSystem({ // Update the dataRoot of the new user await reference.dataRoot.update(oldRootCID, ucan) - // Store the accountDID, which is used to namespace the readKey + // Store the read key, which is namespaced using the account DID await RootKey.store({ accountDID: newRootDID, crypto: crypto, @@ -169,7 +171,7 @@ export async function recoverFileSystem({ }) return { - success: true + success: true, } } catch (error) { return { From faed0654c360c78c242f700d97b70d768087a8aa Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 07:59:00 -0800 Subject: [PATCH 12/18] Fix: call DID.agent directly --- src/filesystem.ts | 6 +++--- src/index.ts | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 06c2a5aec..f8ad66065 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -12,6 +12,8 @@ import * as Ucan from "./ucan/index.js" import * as RootKey from "./common/root-key.js" +import * as DID from "./did/index.js" + import { Branch } from "./path/index.js" import { Configuration } from "./configuration.js" import { Maybe, decodeCID, EMPTY_CID } from "./common/index.js" @@ -117,21 +119,19 @@ export async function loadFileSystem({ config, dependencies, rootKey, username } * Recover a user's file system. */ export async function recoverFileSystem({ - agentDID, auth, dependencies, oldUsername, newUsername, readKey, }: { - agentDID: () => Promise auth: AuthenticationStrategy dependencies: Dependencies } & RecoverFileSystemParams): Promise<{ success: boolean }> { try { const { crypto, reference, storage } = dependencies - const newRootDID = await agentDID() + const newRootDID = await DID.agent(dependencies.crypto) // Register a new user with the `newUsername` const { success } = await auth.register({ diff --git a/src/index.ts b/src/index.ts index 63762488d..2ee2a8377 100644 --- a/src/index.ts +++ b/src/index.ts @@ -494,16 +494,17 @@ export async function assemble(config: Configuration, components: Components): P } - // AgentDID - const agentDID = () => DID.agent(components.crypto) - // Shorthands const shorthands: ShortHands = { loadFileSystem: (username: string) => loadFileSystem({ config, username, dependencies: components }), recoverFileSystem: (params: RecoverFileSystemParams) => - recoverFileSystem({ agentDID, auth, dependencies: components, ...params }), - agentDID, + recoverFileSystem({ + auth, + dependencies: components, + ...params, + }), + agentDID: () => DID.agent(components.crypto), sharingDID: () => DID.sharing(components.crypto), } From 7ebc9766fb062093560a68f9ffd55b7086c4ae2f Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 08:05:14 -0800 Subject: [PATCH 13/18] Chore: remove try/catch so error can be consumed from the callsite --- src/filesystem.ts | 93 ++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index f8ad66065..4673e5906 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -128,55 +128,50 @@ export async function recoverFileSystem({ auth: AuthenticationStrategy dependencies: Dependencies } & RecoverFileSystemParams): Promise<{ success: boolean }> { - try { - const { crypto, reference, storage } = dependencies - - const newRootDID = await DID.agent(dependencies.crypto) - - // Register a new user with the `newUsername` - const { success } = await auth.register({ - username: newUsername, - }) - if (!success) { - throw new Error("Failed to register new user") - } - - // Build an ephemeral UCAN to authorize the dataRoot.update call - const proof: string | null = await storage.getItem( - storage.KEYS.ACCOUNT_UCAN - ) - const ucan = await Ucan.build({ - dependencies, - potency: "APPEND", - resource: "*", - proof: proof ? proof : undefined, - lifetimeInSeconds: 60 * 3, // Three minutes - audience: newRootDID, - issuer: newRootDID, - }) - - const oldRootCID = await reference.dataRoot.lookup(oldUsername) - if (!oldRootCID) { - throw new Error("Failed to lookup oldUsername") - } - - // Update the dataRoot of the new user - await reference.dataRoot.update(oldRootCID, ucan) - - // Store the read key, which is namespaced using the account DID - await RootKey.store({ - accountDID: newRootDID, - crypto: crypto, - readKey, - }) - - return { - success: true, - } - } catch (error) { - return { - success: false - } + + const { crypto, reference, storage } = dependencies + + const newRootDID = await DID.agent(dependencies.crypto) + + // Register a new user with the `newUsername` + const { success } = await auth.register({ + username: newUsername, + }) + if (!success) { + throw new Error("Failed to register new user") + } + + // Build an ephemeral UCAN to authorize the dataRoot.update call + const proof: string | null = await storage.getItem( + storage.KEYS.ACCOUNT_UCAN + ) + const ucan = await Ucan.build({ + dependencies, + potency: "APPEND", + resource: "*", + proof: proof ? proof : undefined, + lifetimeInSeconds: 60 * 3, // Three minutes + audience: newRootDID, + issuer: newRootDID, + }) + + const oldRootCID = await reference.dataRoot.lookup(oldUsername) + if (!oldRootCID) { + throw new Error("Failed to lookup oldUsername") + } + + // Update the dataRoot of the new user + await reference.dataRoot.update(oldRootCID, ucan) + + // Store the read key, which is namespaced using the account DID + await RootKey.store({ + accountDID: newRootDID, + crypto: crypto, + readKey, + }) + + return { + success: true, } } From 5d0d24d91916414f5bf40163fc0563dc33d4a197 Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 09:33:11 -0800 Subject: [PATCH 14/18] Chore: bump version to 0.36.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8085b9cd6..0b0af4431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### v0.35.3 +### v0.36.0 Adds `program.recoverFileSystem({ newUsername, oldUsername, readKey })` shorthand method so apps will no longer have to implement the FS recovery flow manually. From eb84b2aa59a0f5ce9c40e3a8667361e06f693e3f Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 09:52:26 -0800 Subject: [PATCH 15/18] Fix: re-order imports --- src/filesystem.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 4673e5906..26cfc5e1c 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -1,26 +1,23 @@ import { CID } from "multiformats/cid" +import * as Crypto from "./components/crypto/implementation.js" import * as Depot from "./components/depot/implementation.js" -import * as Reference from "./components/reference/implementation.js" - +import * as DID from "./did/index.js" import * as Protocol from "./fs/protocol/index.js" -import * as Versions from "./fs/versions.js" - -import FileSystem, { Dependencies } from "./fs/filesystem.js" - -import * as Ucan from "./ucan/index.js" - +import * as Reference from "./components/reference/implementation.js" import * as RootKey from "./common/root-key.js" +import * as Storage from "./components/storage/implementation.js" +import * as Ucan from "./ucan/index.js" +import * as Versions from "./fs/versions.js" -import * as DID from "./did/index.js" - +import { AuthenticationStrategy } from "./index.js" import { Branch } from "./path/index.js" import { Configuration } from "./configuration.js" +import { Dependencies } from "./fs/filesystem.js" import { Maybe, decodeCID, EMPTY_CID } from "./common/index.js" - import { type RecoverFileSystemParams } from "./fs/types/params.js" -import { AuthenticationStrategy } from "./index.js" +import FileSystem from "./fs/filesystem.js" /** @@ -120,15 +117,18 @@ export async function loadFileSystem({ config, dependencies, rootKey, username } */ export async function recoverFileSystem({ auth, - dependencies, oldUsername, newUsername, readKey, }: { auth: AuthenticationStrategy - dependencies: Dependencies } & RecoverFileSystemParams): Promise<{ success: boolean }> { + const dependencies = { + crypto: Crypto, + reference: Reference, + storage: Storage, + } const { crypto, reference, storage } = dependencies const newRootDID = await DID.agent(dependencies.crypto) From 322d3ccd8de630dfc215460d72f3a3e9110e970d Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 10:01:34 -0800 Subject: [PATCH 16/18] Chore: add readme link to how to generate a Recovery Kit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8f700d26..b62c3768d 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ __Notes:__ - You can use alternative authentication strategies, such as [webnative-walletauth](https://github.com/fission-codes/webnative-walletauth). - You can remove all traces of the user using `await session.destroy()` - You can load the file system separately if you're using a web worker. This is done using the combination of `configuration.fileSystem.loadImmediately = false` and `program.loadFileSystem()` -- You can recover a file system if you've downloaded a Recovery Kit by calling `program.recoverFileSystem({ newUsername, oldUsername, readKey })`. The `oldUsername` and `readKey` can be parsed from the uploaded Recovery Kit and the `newUsername` can be generated before calling the function. Please refer to [this example](https://github.com/webnative-examples/webnative-app-template/blob/5498e7062a4578028b8b55d2ac4c611bd5daab85/src/components/auth/recover/HasRecoveryKit.svelte#L49) from Fission's Webnative App Template +- You can recover a file system if you've downloaded a Recovery Kit by calling `program.recoverFileSystem({ newUsername, oldUsername, readKey })`. The `oldUsername` and `readKey` can be parsed from the uploaded Recovery Kit and the `newUsername` can be generated before calling the function. Please refer to [this example](https://github.com/webnative-examples/webnative-app-template/blob/5498e7062a4578028b8b55d2ac4c611bd5daab85/src/components/auth/recover/HasRecoveryKit.svelte#L49) from Fission's Webnative App Template. Additionally, if you would like to see how to generate a Recovery Kit, you can reference [this example](https://github.com/webnative-examples/webnative-app-template/blob/main/src/lib/account-settings.ts#L186) ## Working with the file system From 52cf72bdecb5ca3de4675c53237c585ac4214fbb Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 10:10:48 -0800 Subject: [PATCH 17/18] Fix: only pass in necessary components to recoverFileSystem --- src/filesystem.ts | 17 ++++++++--------- src/index.ts | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/filesystem.ts b/src/filesystem.ts index 26cfc5e1c..8c3c6efc9 100644 --- a/src/filesystem.ts +++ b/src/filesystem.ts @@ -117,21 +117,22 @@ export async function loadFileSystem({ config, dependencies, rootKey, username } */ export async function recoverFileSystem({ auth, + dependencies, oldUsername, newUsername, readKey, }: { auth: AuthenticationStrategy + dependencies: { + crypto: Crypto.Implementation + reference: Reference.Implementation + storage: Storage.Implementation + } } & RecoverFileSystemParams): Promise<{ success: boolean }> { - const dependencies = { - crypto: Crypto, - reference: Reference, - storage: Storage, - } const { crypto, reference, storage } = dependencies - const newRootDID = await DID.agent(dependencies.crypto) + const newRootDID = await DID.agent(crypto) // Register a new user with the `newUsername` const { success } = await auth.register({ @@ -142,9 +143,7 @@ export async function recoverFileSystem({ } // Build an ephemeral UCAN to authorize the dataRoot.update call - const proof: string | null = await storage.getItem( - storage.KEYS.ACCOUNT_UCAN - ) + const proof: string | null = await storage.getItem(storage.KEYS.ACCOUNT_UCAN) const ucan = await Ucan.build({ dependencies, potency: "APPEND", diff --git a/src/index.ts b/src/index.ts index 2ee2a8377..ad0d56ca0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -501,7 +501,7 @@ export async function assemble(config: Configuration, components: Components): P recoverFileSystem: (params: RecoverFileSystemParams) => recoverFileSystem({ auth, - dependencies: components, + dependencies: { crypto: components.crypto, reference: components.reference, storage: components.storage }, ...params, }), agentDID: () => DID.agent(components.crypto), From 4b25f37d3c8ad749d7e299a4f90d568aab449f29 Mon Sep 17 00:00:00 2001 From: avivash Date: Fri, 13 Jan 2023 13:44:17 -0800 Subject: [PATCH 18/18] Signing this commit