8000 Avivash/File System Recovery Shorthand Method by avivash · Pull Request #461 · oddsdk/ts-odd · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Avivash/File System Recovery Shorthand Method #461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### v0.36.0

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.
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/webnativ 10000 e-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
Expand Down
78 changes: 73 additions & 5 deletions src/filesystem.ts
Original file line number Diff line number Diff line change
@@ -1,16 +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 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 FileSystem, { Dependencies } from "./fs/filesystem.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 FileSystem from "./fs/filesystem.js"


/**
Expand Down Expand Up @@ -105,6 +112,67 @@ export async function loadFileSystem({ config, dependencies, rootKey, username }
return fs
}

/**
* Recover a user's file system.
*/
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 { crypto, reference, storage } = dependencies

const newRootDID = await DID.agent(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,
}
}


// VERSIONING
Expand Down Expand Up @@ -209,4 +277,4 @@ async function getDataRoot(
resolve(dataCid?.toString() === EMPTY_CID ? null : dataCid)
}, retryInterval)
})
}
}
5 changes: 5 additions & 0 deletions src/fs/types/params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type RecoverFileSystemParams = {
newUsername: string
oldUsername: string
readKey: Uint8Array
}
25 changes: 21 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.js"


// 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"
Expand Down Expand Up @@ -143,9 +150,13 @@ export enum ProgramError {
UnsupportedBrowser = "UNSUPPORTED_BROWSER"
}


export type ShortHands = {
loadFileSystem: (username: string) => Promise<FileSystem>
recoverFileSystem: ({
newUsername,
oldUsername,
readKey,
}: RecoverFileSystemParams) => Promise<{ success: boolean }>
agentDID: () => Promise<string>
sharingDID: () => Promise<string>
}
Expand Down Expand Up @@ -485,8 +496,14 @@ 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({
auth,
dependencies: { crypto: components.crypto, reference: components.reference, storage: components.storage },
...params,
}),
agentDID: () => DID.agent(components.crypto),
sharingDID: () => DID.sharing(components.crypto),
}
Expand Down
0