diff --git a/package-lock.json b/package-lock.json
index e73cde6..696baf7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,11 +9,14 @@
"version": "0.1.0",
"dependencies": {
"@fission-codes/homestar": "^1.0.0",
+ "@fission-codes/ucan": "^0.0.1",
"@oddjs/odd": "0.37.0",
"@zerodevx/svelte-json-view": "^1.0.7",
"chart.js": "^4.4.0",
"clipboard-copy": "^4.0.1",
"iso-base": "^2.0.1",
+ "iso-signatures": "^0.2.0",
+ "iso-web": "^0.3.1",
"localforage": "^1.10.0",
"marked": "^9.0.3",
"multiformats": "^12.1.3",
@@ -971,6 +974,17 @@
"@esbuild/win32-x64": "0.19.8"
}
},
+ "node_modules/@fission-codes/ucan": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@fission-codes/ucan/-/ucan-0.0.1.tgz",
+ "integrity": "sha512-sW7e7a4uXYRc7DMKY8/JQBcNuEyq1cbOtueOuGWoy1Wfa2rSfWDRLUBV9NibFJK3jXrd9h23INOZMWcXOqMEPQ==",
+ "dependencies": {
+ "iso-base": "^2.0.1",
+ "iso-did": "^1.4.0",
+ "iso-signatures": "^0.2.0",
+ "multiformats": "^12.1.3"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
@@ -1348,6 +1362,17 @@
"multiformats": "^12.1.0"
}
},
+ "node_modules/@noble/ed25519": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-2.0.0.tgz",
+ "integrity": "sha512-/extjhkwFupyopDrt80OMWKdLgP429qLZj+z6sYJz90rF2Iz0gjZh2ArMKPImUl13Kx+0EXI2hN9T/KJV0/Zng==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1755,6 +1780,11 @@
"integrity": "sha512-uTuEgFXMknpun//Jj6b1R8T8LiMi9fNpH+cnhZr4b7col2HHTMmjYfm/WOZ7nzjuGpk+oTrpHhePe1qlWtHWTA==",
"dev": true
},
+ "node_modules/@types/retry": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
+ "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="
+ },
"node_modules/@types/sass": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.45.0.tgz",
@@ -3207,6 +3237,11 @@
"integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==",
"dev": true
},
+ "node_modules/did-resolver": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-4.1.0.tgz",
+ "integrity": "sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA=="
+ },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -4145,6 +4180,11 @@
"entities": "^4.4.0"
}
},
+ "node_modules/idb-keyval": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
+ "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -4545,6 +4585,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-network-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.1.tgz",
+ "integrity": "sha512-OwQXkwBJeESyhFw+OumbJVD58BFBJJI5OM5S1+eyrDKlgDZPX2XNT5gXS56GSD3NPbbwUuMlR1Q71SRp5SobuQ==",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -4620,6 +4671,50 @@
"bigint-mod-arith": "^3.3.1"
}
},
+ "node_modules/iso-did": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/iso-did/-/iso-did-1.5.0.tgz",
+ "integrity": "sha512-SkMUONxelLV5yipdNaGUqe/1KiKu/pVTBJ46/HbwLtzm6IC2YuJ8E9w7DpwZsnh0G2AlJ+J7i/8ijcZCOp8DWw==",
+ "dependencies": {
+ "did-resolver": "^4.1.0",
+ "iso-base": "^2.0.1",
+ "iso-web": "^0.3.1",
+ "multiformats": "^13.0.0"
+ }
+ },
+ "node_modules/iso-did/node_modules/multiformats": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.0.0.tgz",
+ "integrity": "sha512-xiIB0p7EKmETm3wyKedOg/xuyQ18PoWwXCzzgpZAiDxL9ktl3XTh8AqoDT5kAqRg+DU48XAGPsUJL2Rn6Bx3Lw=="
+ },
+ "node_modules/iso-kv": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/iso-kv/-/iso-kv-0.2.0.tgz",
+ "integrity": "sha512-n4q64QQO6GPZSeJsTPsU6jHijyDgMb18RCcQ5t065S3p1ddktF1B8tlLhqbcIDqC8ORl77fs7KgTMJDvrccQ9w==",
+ "dependencies": {
+ "idb-keyval": "^6.2.1",
+ "kysely": "^0.26.3"
+ }
+ },
+ "node_modules/iso-signatures": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/iso-signatures/-/iso-signatures-0.2.0.tgz",
+ "integrity": "sha512-OfgejGIG7GiCwO5QhcjOTSUJx8Fk+oeWG9GTqAT7eBs4IxqAXCXUAUIRSf9FOr4d39R6y4480pCMz+Aht6/Fgg==",
+ "dependencies": {
+ "@noble/ed25519": "^2.0.0",
+ "iso-base": "^2.0.1",
+ "iso-did": "^1.4.0"
+ }
+ },
+ "node_modules/iso-web": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/iso-web/-/iso-web-0.3.1.tgz",
+ "integrity": "sha512-i63X/p7wHvdTLnA2QgWklDozFkAvOYnxAVmYrUV2M40jDLPFPE7G4utZc7b3SpX4TxQ5GpObn1Cpg7oOne9UNw==",
+ "dependencies": {
+ "iso-kv": "^0.2.0",
+ "p-retry": "^6.2.0"
+ }
+ },
"node_modules/iso-websocket": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/iso-websocket/-/iso-websocket-0.1.6.tgz",
@@ -4873,6 +4968,14 @@
"node": ">=6"
}
},
+ "node_modules/kysely": {
+ "version": "0.26.3",
+ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.26.3.tgz",
+ "integrity": "sha512-yWSgGi9bY13b/W06DD2OCDDHQmq1kwTGYlQ4wpZkMOJqMGCstVCFIvxCCVG4KfY1/3G0MhDAcZsip/Lw8/vJWw==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/level": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz",
@@ -5508,6 +5611,30 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-retry": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz",
+ "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==",
+ "dependencies": {
+ "@types/retry": "0.12.2",
+ "is-network-error": "^1.0.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=16.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-retry/node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/p-timeout": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz",
@@ -8018,6 +8145,17 @@
}
}
},
+ "@fission-codes/ucan": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@fission-codes/ucan/-/ucan-0.0.1.tgz",
+ "integrity": "sha512-sW7e7a4uXYRc7DMKY8/JQBcNuEyq1cbOtueOuGWoy1Wfa2rSfWDRLUBV9NibFJK3jXrd9h23INOZMWcXOqMEPQ==",
+ "requires": {
+ "iso-base": "^2.0.1",
+ "iso-did": "^1.4.0",
+ "iso-signatures": "^0.2.0",
+ "multiformats": "^12.1.3"
+ }
+ },
"@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
@@ -8300,6 +8438,11 @@
"multiformats": "^12.1.0"
}
},
+ "@noble/ed25519": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-2.0.0.tgz",
+ "integrity": "sha512-/extjhkwFupyopDrt80OMWKdLgP429qLZj+z6sYJz90rF2Iz0gjZh2ArMKPImUl13Kx+0EXI2hN9T/KJV0/Zng=="
+ },
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -8624,6 +8767,11 @@
"integrity": "sha512-uTuEgFXMknpun//Jj6b1R8T8LiMi9fNpH+cnhZr4b7col2HHTMmjYfm/WOZ7nzjuGpk+oTrpHhePe1qlWtHWTA==",
"dev": true
},
+ "@types/retry": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
+ "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="
+ },
"@types/sass": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.45.0.tgz",
@@ -9604,6 +9752,11 @@
"integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==",
"dev": true
},
+ "did-resolver": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-4.1.0.tgz",
+ "integrity": "sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA=="
+ },
"didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -10297,6 +10450,11 @@
"entities": "^4.4.0"
}
},
+ "idb-keyval": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
+ "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
+ },
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -10570,6 +10728,11 @@
"is-extglob": "^2.1.1"
}
},
+ "is-network-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.1.tgz",
+ "integrity": "sha512-OwQXkwBJeESyhFw+OumbJVD58BFBJJI5OM5S1+eyrDKlgDZPX2XNT5gXS56GSD3NPbbwUuMlR1Q71SRp5SobuQ=="
+ },
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -10624,6 +10787,52 @@
"bigint-mod-arith": "^3.3.1"
}
},
+ "iso-did": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/iso-did/-/iso-did-1.5.0.tgz",
+ "integrity": "sha512-SkMUONxelLV5yipdNaGUqe/1KiKu/pVTBJ46/HbwLtzm6IC2YuJ8E9w7DpwZsnh0G2AlJ+J7i/8ijcZCOp8DWw==",
+ "requires": {
+ "did-resolver": "^4.1.0",
+ "iso-base": "^2.0.1",
+ "iso-web": "^0.3.1",
+ "multiformats": "^13.0.0"
+ },
+ "dependencies": {
+ "multiformats": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.0.0.tgz",
+ "integrity": "sha512-xiIB0p7EKmETm3wyKedOg/xuyQ18PoWwXCzzgpZAiDxL9ktl3XTh8AqoDT5kAqRg+DU48XAGPsUJL2Rn6Bx3Lw=="
+ }
+ }
+ },
+ "iso-kv": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/iso-kv/-/iso-kv-0.2.0.tgz",
+ "integrity": "sha512-n4q64QQO6GPZSeJsTPsU6jHijyDgMb18RCcQ5t065S3p1ddktF1B8tlLhqbcIDqC8ORl77fs7KgTMJDvrccQ9w==",
+ "requires": {
+ "idb-keyval": "^6.2.1",
+ "kysely": "^0.26.3"
+ }
+ },
+ "iso-signatures": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/iso-signatures/-/iso-signatures-0.2.0.tgz",
+ "integrity": "sha512-OfgejGIG7GiCwO5QhcjOTSUJx8Fk+oeWG9GTqAT7eBs4IxqAXCXUAUIRSf9FOr4d39R6y4480pCMz+Aht6/Fgg==",
+ "requires": {
+ "@noble/ed25519": "^2.0.0",
+ "iso-base": "^2.0.1",
+ "iso-did": "^1.4.0"
+ }
+ },
+ "iso-web": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/iso-web/-/iso-web-0.3.1.tgz",
+ "integrity": "sha512-i63X/p7wHvdTLnA2QgWklDozFkAvOYnxAVmYrUV2M40jDLPFPE7G4utZc7b3SpX4TxQ5GpObn1Cpg7oOne9UNw==",
+ "requires": {
+ "iso-kv": "^0.2.0",
+ "p-retry": "^6.2.0"
+ }
+ },
"iso-websocket": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/iso-websocket/-/iso-websocket-0.1.6.tgz",
@@ -10821,6 +11030,11 @@
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true
},
+ "kysely": {
+ "version": "0.26.3",
+ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.26.3.tgz",
+ "integrity": "sha512-yWSgGi9bY13b/W06DD2OCDDHQmq1kwTGYlQ4wpZkMOJqMGCstVCFIvxCCVG4KfY1/3G0MhDAcZsip/Lw8/vJWw=="
+ },
"level": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz",
@@ -11263,6 +11477,23 @@
"p-timeout": "^5.0.2"
}
},
+ "p-retry": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz",
+ "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==",
+ "requires": {
+ "@types/retry": "0.12.2",
+ "is-network-error": "^1.0.0",
+ "retry": "^0.13.1"
+ },
+ "dependencies": {
+ "retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="
+ }
+ }
+ },
"p-timeout": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz",
diff --git a/package.json b/package.json
index dfe72d8..de0bcdd 100644
--- a/package.json
+++ b/package.json
@@ -58,11 +58,14 @@
},
"dependencies": {
"@fission-codes/homestar": "^1.0.0",
+ "@fission-codes/ucan": "^0.0.1",
"@oddjs/odd": "0.37.0",
"@zerodevx/svelte-json-view": "^1.0.7",
"chart.js": "^4.4.0",
"clipboard-copy": "^4.0.1",
"iso-base": "^2.0.1",
+ "iso-signatures": "^0.2.0",
+ "iso-web": "^0.3.1",
"localforage": "^1.10.0",
"marked": "^9.0.3",
"multiformats": "^12.1.3",
diff --git a/src/components/auth/backup/AreYouSure.svelte b/src/components/auth/backup/AreYouSure.svelte
deleted file mode 100644
index 120bec8..0000000
--- a/src/components/auth/backup/AreYouSure.svelte
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
Are you sure?
-
-
- Without a backup device, if you lose this device or reset your browser,
- you will not be able to recover your account data.
-
-
-
goto('/delegate-account')}
- >
- Connect a backup device
-
-
- YOLO—I'll risk just one device for now
-
-
-
-
diff --git a/src/components/auth/backup/Backup.svelte b/src/components/auth/backup/Backup.svelte
deleted file mode 100644
index 0527306..0000000
--- a/src/components/auth/backup/Backup.svelte
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
Backup your account
-
- Your {appName} account & its data live only on your devices.
-
-
-
- We highly recommend backing up your account on at least one additional
- device.
-
-
-
goto('/delegate-account')}
- >
- Connect a backup device
-
-
navigate('are-you-sure')}
- >
- Skip for now
-
-
-
-
diff --git a/src/components/auth/delegate-account/ConnectBackupDevice.svelte b/src/components/auth/delegate-account/ConnectBackupDevice.svelte
deleted file mode 100644
index 1b19879..0000000
--- a/src/components/auth/delegate-account/ConnectBackupDevice.svelte
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
Connect a backup device
-
- {@html qrcode}
-
-
- Scan this code on the new device, or share the connection link.
-
-
-
- Share connection link
-
- {#if !backupCreated}
-
goto('/backup?view=are-you-sure')}
- >
- Skip for now
-
- {:else}
-
- Cancel
-
- {/if}
-
-
-
diff --git a/src/components/auth/delegate-account/DelegateAccount.svelte b/src/components/auth/delegate-account/DelegateAccount.svelte
deleted file mode 100644
index ff5d236..0000000
--- a/src/components/auth/delegate-account/DelegateAccount.svelte
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
- A new device would like to connect to your account
-
-
-
-
- {#if !pinError}
-
- Enter the connection code from that device to approve this
- connection.
-
- {:else}
-
- Entered pin does not match a pin from a known device.
-
- {/if}
-
-
-
-
- Cancel Request
-
-
-
-
-
diff --git a/src/components/auth/link-device/LinkDevice.svelte b/src/components/auth/link-device/LinkDevice.svelte
deleted file mode 100644
index ecebad1..0000000
--- a/src/components/auth/link-device/LinkDevice.svelte
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
-
-
Connect to {appName}
-
- {#if pin}
-
- {pin}
-
- {/if}
-
- Enter this code on your connected device.
-
-
-
- Waiting for a response...
-
-
-
-
- Cancel Request
-
-
-
-
-
diff --git a/src/components/auth/recover/HasRecoveryKit.svelte b/src/components/auth/recover/HasRecoveryKit.svelte
deleted file mode 100644
index 1828927..0000000
--- a/src/components/auth/recover/HasRecoveryKit.svelte
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
Recover your account
-
- {#if state === RECOVERY_STATES.Done}
-
- Account recovered!
-
-
- Welcome back {$sessionStore.username.trimmed}.
- We were able to successfully recover all of your private data.
-
- {:else}
-
- If you’ve lost access to all of your connected devices, you can use your
- recovery kit to restore access to your private data.
-
- {/if}
-
- {#if state === RECOVERY_STATES.Error}
-
- We were unable to recover your account. Please double check that you
- uploaded the correct file.
-
- {/if}
-
-
-
-
- {#if state !== RECOVERY_STATES.Done}
-
- {`It should be a file named ODD-RecoveryKit-{yourUsername}.txt`}
-
- {/if}
-
-
diff --git a/src/components/auth/recover/RecoveryKitButton.svelte b/src/components/auth/recover/RecoveryKitButton.svelte
deleted file mode 100644
index d309866..0000000
--- a/src/components/auth/recover/RecoveryKitButton.svelte
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-{#if state === RECOVERY_STATES.Ready || state === RECOVERY_STATES.Error}
-
- Upload your recovery kit
-
-
-{:else}
- {@const { $$on_click, ...props } = buttonData[state].props}
-
- {#if state === RECOVERY_STATES.Processing}
-
- {/if}
- {buttonData[state].text}
- {#if state === RECOVERY_STATES.Done}
-
- {/if}
-
-{/if}
diff --git a/src/components/auth/register/Register.svelte b/src/components/auth/register/Register.svelte
deleted file mode 100644
index 4b57c60..0000000
--- a/src/components/auth/register/Register.svelte
+++ /dev/null
@@ -1,190 +0,0 @@
-
-
-{#if initializingFilesystem}
-
-{:else}
-
-
Connect this device
-
-
-
-
-
-
-
- I have an existing account
-
- {#if existingAccount}
-
-
- Which device are you connected on?
-
-
To connect your existing account, you'll need to:
-
- Find a device the account is already connected on
- Navigate to your Account Settings
- Click "Connect a new device"
-
-
- {/if}
-
-
-
-
Recover an account
-
-{/if}
diff --git a/src/components/auth/register/Welcome.svelte b/src/components/auth/register/Welcome.svelte
deleted file mode 100644
index 68e08e2..0000000
--- a/src/components/auth/register/Welcome.svelte
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
- Welcome, {$sessionStore.username.trimmed}!
-
-
-
-
-
-
Your account has been created.
-
-
-
-
- Wait—what's my password?
-
-
- You don't need a password!
- {appName} uses public key cryptography to authenticate you with this
- device.
-
-
-
-
Continue
-
-
-
-
diff --git a/src/components/home/sign-up/Email.svelte b/src/components/home/sign-up/Email.svelte
index fc56afd..df8c4b6 100644
--- a/src/components/home/sign-up/Email.svelte
+++ b/src/components/home/sign-up/Email.svelte
@@ -12,6 +12,7 @@
// Submit email to Fission server to register the account
const handleSubmitEmail = async (event: Event) => {
loading = true
+
try {
const formEl = event.target as HTMLFormElement
const data = new FormData(formEl)
@@ -19,6 +20,20 @@
posthog.capture('Email validation sent')
+ const response = await fetch(
+ 'http://localhost:3000/api/v0/auth/email/verify',
+ {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ email: email.toString() })
+ }
+ )
+
+ console.log('Response', await response.text())
+
dispatch('nextStep', { email })
// addNotification({ msg: 'Account created!', type: 'success'})
@@ -26,6 +41,7 @@
console.error(error)
addNotification({ msg: 'Failed to register account', type: 'error' })
}
+
loading = false
}
diff --git a/src/components/home/sign-up/Pin.svelte b/src/components/home/sign-up/Pin.svelte
index b19b87e..5345be2 100644
--- a/src/components/home/sign-up/Pin.svelte
+++ b/src/components/home/sign-up/Pin.svelte
@@ -20,9 +20,10 @@
const data = new FormData(formEl)
const pin = data.get('pin')
+ // TODO: Is this correct? Should we perhaps only emit this on the next step?
posthog.capture('Account created')
- dispatch('nextStep', { pin })
+ dispatch('nextStep', { email, pin })
// addNotification({ msg: 'Account created!', type: 'success' })
} catch (error) {
@@ -34,7 +35,20 @@
}
const handleResendEmail = async () => {
- addNotification({ msg: 'Email sent!', type: 'success' })
+ try {
+ await fetch('http://localhost:3000/api/v0/auth/email/verify', {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ email: email.toString() })
+ })
+ addNotification({ msg: 'Email sent!', type: 'success' })
+ } catch (error) {
+ console.error('error')
+ addNotification({ msg: 'Failed to re-send email', type: 'error' })
+ }
}
diff --git a/src/components/home/sign-up/Username.svelte b/src/components/home/sign-up/Username.svelte
index 553b927..f0f1425 100644
--- a/src/components/home/sign-up/Username.svelte
+++ b/src/components/home/sign-up/Username.svelte
@@ -1,9 +1,20 @@
-
-{#if $accountSettingsStore.avatar}
- {#if $accountSettingsStore.loading}
-
-
-
- {:else}
-
- {/if}
-{:else}
-
- {$sessionStore.username.trimmed[0]}
-
-{/if}
diff --git a/src/components/settings/AvatarUpload.svelte b/src/components/settings/AvatarUpload.svelte
deleted file mode 100644
index 0d52afc..0000000
--- a/src/components/settings/AvatarUpload.svelte
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
Avatar
-
-
-
-
- Upload a new avatar
-
-
-
-
diff --git a/src/components/settings/ConnectedDevices.svelte b/src/components/settings/ConnectedDevices.svelte
deleted file mode 100644
index ed01274..0000000
--- a/src/components/settings/ConnectedDevices.svelte
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
Connected devices
- {#if $sessionStore.backupCreated}
-
You have connected at least one other device.
- {:else}
-
You have no other connected devices.
- {/if}
-
goto('/delegate-account')}
- >
- Connect an additional device
-
-
diff --git a/src/components/settings/RecoveryKit.svelte b/src/components/settings/RecoveryKit.svelte
deleted file mode 100644
index 392f3d4..0000000
--- a/src/components/settings/RecoveryKit.svelte
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
Recovery Kit
-
- Your recovery kit will restore access to your data in the event that you
- lose access to all of your connected devices. We recommend you store your
- kit in a safe place, separate from those devices.
-
-
-
- Create your recovery kit
-
-
-
-{#if modalOpen}
-
-{/if}
diff --git a/src/components/settings/RecoveryKitModal.svelte b/src/components/settings/RecoveryKitModal.svelte
deleted file mode 100644
index 4eecbd4..0000000
--- a/src/components/settings/RecoveryKitModal.svelte
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
- ✕
-
-
-
- {#await recoveryKitPromise}
-
Creating your recovery kit...
-
-
-
-
- {:then}
-
Your recovery kit has been created!
-
-
-
Please store it somewhere safe for two reasons:
-
-
- It is powerful:
- Anyone with this recovery kit will have access to all of your private
- data.
-
-
- It's your backup plan:
- If you lose access to your connected devices, this kit will help you
- recover your private data.
-
-
-
- So, keep it somewhere you keep things you don't want to lose or have
- stolen.
-
-
-
-
-
- Download recovery kit
-
- {/await}
-
-
-
diff --git a/src/components/settings/TruncatedUsername.svelte b/src/components/settings/TruncatedUsername.svelte
deleted file mode 100644
index a64f279..0000000
--- a/src/components/settings/TruncatedUsername.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-{usernameParts[0]}
-
- #{usernameParts[1].substring(0, 12)}...{usernameParts[1].substring(
- usernameParts[1].length - 5
- )}
-
diff --git a/src/components/settings/Username.svelte b/src/components/settings/Username.svelte
index 9af4055..2cbffbb 100644
--- a/src/components/settings/Username.svelte
+++ b/src/components/settings/Username.svelte
@@ -4,10 +4,9 @@
import { sessionStore } from '$lib/stores'
import { addNotification } from '$lib/notifications'
import ClipboardIcon from '$components/icons/ClipboardIcon.svelte'
- import TruncatedUsername from '$components/settings/TruncatedUsername.svelte'
const handleCopyUsername = async (): Promise => {
- await clipboardCopy($sessionStore.username.full)
+ await clipboardCopy($sessionStore.username)
addNotification({ msg: 'Copied to clipboard', type: 'success' })
}
@@ -16,7 +15,7 @@
Username
-
+ {$sessionStore.username}
=> {
- const fs = getStore(filesystemStore)
-
- // Return if user has not uploaded an avatar yet
- const avatarDirExists = await fs.exists(AVATAR_DIR)
- if (!avatarDirExists) {
- return
- }
-
- // Find the filename of the old avatar
- const links = await fs.ls(AVATAR_DIR)
- const oldAvatarFileName = Object.keys(links).find(key =>
- key.includes(AVATAR_FILE_NAME)
- )
- const oldFileNameArray = oldAvatarFileName.split('.')[ 0 ]
- const archiveFileName = `${oldFileNameArray[ 0 ]}-${Date.now()}.${oldFileNameArray[ 1 ]
- }`
-
- // Move old avatar to archive dir
- const fromPath = odd.path.combine(AVATAR_DIR, odd.path.file(oldAvatarFileName))
- const toPath = odd.path.combine(AVATAR_ARCHIVE_DIR, odd.path.file(archiveFileName))
- await fs.mv(fromPath, toPath)
-
- // Announce the changes to the server
- await fs.publish()
-}
-
-/**
- * Get the Avatar from the user's WNFS and construct its `src`
- */
-export const getAvatarFromWNFS = async (): Promise => {
- try {
- // Set loading: true on the accountSettingsStore
- accountSettingsStore.update(store => ({ ...store, loading: true }))
-
- const fs = getStore(filesystemStore)
-
- // If the avatar dir doesn't exist, silently fail and let the UI handle it
- const avatarDirExists = await fs.exists(AVATAR_DIR)
- if (!avatarDirExists) {
- accountSettingsStore.update(store => ({
- ...store,
- loading: false
- }))
- return
- }
-
- // Find the file that matches the AVATAR_FILE_NAME
- const links = await fs.ls(AVATAR_DIR)
- const avatarName = Object.keys(links).find(key =>
- key.includes(AVATAR_FILE_NAME)
- )
-
- // If user has not uploaded an avatar, silently fail and let the UI handle it
- if (!avatarName) {
- accountSettingsStore.update(store => ({
- ...store,
- loading: false
- }))
- return
- }
-
- const file = await fs.get(odd.path.combine(AVATAR_DIR, odd.path.file(`${avatarName}`)))
-
- // The CID for private files is currently located in `file.header.content`
- const cid = (file as AvatarFile).header.content.toString()
-
- // Create a base64 string to use as the image `src`
- const src = `data:image/jpeg;base64, ${uint8arrays.toString(
- (file as AvatarFile).content,
- 'base64'
- )}`
-
- const avatar = {
- cid,
- ctime: (file as AvatarFile).header.metadata.unixMeta.ctime,
- name: avatarName,
- src
- }
-
- // Push images to the accountSettingsStore
- accountSettingsStore.update(store => ({
- ...store,
- avatar,
- loading: false
- }))
- } catch (error) {
- console.error(error)
- accountSettingsStore.update(store => ({
- ...store,
- avatar: null,
- loading: false
- }))
- }
-}
-
-/**
- * Upload an avatar image to the user's private WNFS
- * @param image
- */
-export const uploadAvatarToWNFS = async (image: File): Promise => {
- try {
- // Set loading: true on the accountSettingsStore
- accountSettingsStore.update(store => ({ ...store, loading: true }))
-
- const fs = getStore(filesystemStore)
-
- // Reject files over 20MB
- const imageSizeInMB = image.size / (1024 * 1024)
- if (imageSizeInMB > FILE_SIZE_LIMIT) {
- throw new Error('Image can be no larger than 20MB')
- }
-
- // Archive old avatar
- await archiveOldAvatar()
-
- // Rename the file to `avatar.[extension]`
- const updatedImage = new File(
- [ image ],
- `${AVATAR_FILE_NAME}.${image.name.split('.')[ 1 ]}`,
- {
- type: image.type
- }
- )
-
- // Create a sub directory and add the avatar
- await fs.write(
- odd.path.combine(AVATAR_DIR, odd.path.file(updatedImage.name)),
- await fileToUint8Array(updatedImage)
- )
-
- // Announce the changes to the server
- await fs.publish()
-
- addNotification({ msg: `Your avatar has been updated!`, type: 'success' })
- } catch (error) {
- addNotification({ msg: error.message, type: 'error' })
- console.error(error)
- }
-}
-
-export const generateRecoveryKit = async (): Promise => {
- const {
- program: {
- components: { crypto, reference }
- },
- username: {
- full,
- hashed,
- trimmed,
- }
- } = getStore(sessionStore)
-
- // Get the user's read-key and base64 encode it
- const accountDID = await reference.didRoot.lookup(hashed)
- const readKey = await retrieve({ crypto, accountDID })
- const encodedReadKey = uint8arrays.toString(readKey, 'base64pad')
-
- // Get today's date to display in the kit
- const options: Intl.DateTimeFormatOptions = {
- weekday: 'short',
- year: 'numeric',
- month: 'short',
- day: 'numeric'
- }
- const date = new Date()
-
- const content = `# %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
-# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-# %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
-# @@@@@% %@@@@@@% %@@@@@@@% %@@@@@
-# @@@@@ @@@@@% @@@@@@ @@@@@
-# @@@@@% @@@@@ %@@@@@ %@@@@@
-# @@@@@@% @@@@@ %@@% @@@@@ %@@@@@@
-# @@@@@@@ @@@@@ %@@@@% @@@@@ @@@@@@@
-# @@@@@@@ @@@@% @@@@@@ @@@@@ @@@@@@@
-# @@@@@@@ %@@@@ @@@@@@ @@@@@% @@@@@@@
-# @@@@@@@ @@@@@ @@@@@@ %@@@@@ @@@@@@@
-# @@@@@@@ @@@@@@@@@@@@@@@@ @@@@@ @@@@@@@
-# @@@@@@@ %@@@@@@@@@@@@@@@ @@@@% @@@@@@@
-# @@@@@@@ %@@% @@@@@@ %@@% @@@@@@@
-# @@@@@@@ @@@@@@ @@@@@@@
-# @@@@@@@% %@@@@@@% %@@@@@@@
-# @@@@@@@@@% %@@@@@@@@@@% %@@@@@@@@@
-# %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
-# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-# %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
-#
-# This is your recovery kit. (It’s a yaml text file)
-#
-# Created for ${trimmed} on ${date.toLocaleDateString('en-US', options)}
-#
-# Store this somewhere safe.
-#
-# Anyone with this file will have read access to your private files.
-# Losing it means you won’t be able to recover your account
-# in case you lose access to all your linked devices.
-#
-# Our team will never ask you to share this file.
-#
-# To use this file, go to ${window.location.origin}/recover/
-# Learn how to customize this kit for your users: https://guide.fission.codes/
-
-username: ${full}
-key: ${encodedReadKey}`
-
- return content
-}
diff --git a/src/lib/auth/account.ts b/src/lib/auth/account.ts
deleted file mode 100644
index 544fff2..0000000
--- a/src/lib/auth/account.ts
+++ /dev/null
@@ -1,152 +0,0 @@
-import * as uint8arrays from 'uint8arrays'
-import { sha256 } from '@oddjs/odd/components/crypto/implementation/browser'
-import { publicKeyToDid } from '@oddjs/odd/did/transformers'
-import * as odd from '@oddjs/odd'
-import type { Crypto } from '@oddjs/odd'
-import type FileSystem from '@oddjs/odd/fs/index'
-import { get as getStore } from 'svelte/store'
-
-import { ACCOUNT_SETTINGS_DIR } from '$lib/account-settings'
-import { getBackupStatus } from '$lib/auth/backup'
-import { filesystemStore, sessionStore } from '$lib/stores'
-import { asyncDebounce } from '$lib/utils'
-import { WORKFLOWS_DIR } from '$lib/workflows'
-
-export const USERNAME_STORAGE_KEY = 'fullUsername'
-
-export enum RECOVERY_STATES {
- Ready,
- Processing,
- Error,
- Done
-}
-
-export const isUsernameValid = async (username: string): Promise => {
- const session = getStore(sessionStore)
- return session.authStrategy.isUsernameValid(username)
-}
-
-const _isUsernameAvailable = async (
- username: string
-) => {
- const session = getStore(sessionStore)
- return session.authStrategy.isUsernameAvailable(username)
-}
-
-const debouncedIsUsernameAvailable = asyncDebounce(
- _isUsernameAvailable,
- 300
-)
-
-export const isUsernameAvailable = async (
- username: string
-): Promise => {
- return debouncedIsUsernameAvailable(username)
-}
-
-export const createDID = async (crypto: Crypto.Implementation): Promise => {
- const pubKey = await crypto.keystore.publicExchangeKey()
- const ksAlg = await crypto.keystore.getAlgorithm()
-
- return publicKeyToDid(crypto, pubKey, ksAlg)
-}
-
-export const prepareUsername = async (username: string): Promise => {
- const normalizedUsername = username.normalize('NFD')
- const hashedUsername = await sha256(
- new TextEncoder().encode(normalizedUsername)
- )
-
- return uint8arrays
- .toString(hashedUsername, 'base32')
- .slice(0, 32)
-}
-
-export const register = async (hashedUsername: string): Promise => {
- const { authStrategy, program: { components: { storage } } } = getStore(sessionStore)
-
- const { success } = await authStrategy.register({ username: hashedUsername })
-
- if (!success) return success
-
- const session = await authStrategy.session()
- filesystemStore.set(session.fs)
-
- // TODO Remove if only public and private directories are needed
- await initializeFilesystem(session.fs)
-
- const fullUsername = await storage.getItem(USERNAME_STORAGE_KEY) as string
-
- sessionStore.update(state => ({
- ...state,
- username: {
- full: fullUsername,
- hashed: hashedUsername,
- trimmed: fullUsername.split('#')[ 0 ]
- },
- session
- }))
-
- return success
-}
-
-/**
- * Create additional directories and files needed by the app
- *
- * @param fs FileSystem
- */
-const initializeFilesystem = async (fs: FileSystem): Promise => {
- await fs.mkdir(WORKFLOWS_DIR)
- await fs.mkdir(ACCOUNT_SETTINGS_DIR)
-}
-
-export const loadAccount = async (hashedUsername: string, fullUsername: string): Promise => {
- const { authStrategy, program: { components: { storage } } } = getStore(sessionStore)
- const session = await authStrategy.session()
-
- filesystemStore.set(session.fs)
-
- const backupStatus = await getBackupStatus(session.fs)
-
- await storage.setItem(USERNAME_STORAGE_KEY, fullUsername)
-
- sessionStore.update(state => ({
- ...state,
- username: {
- full: fullUsername,
- hashed: hashedUsername,
- trimmed: fullUsername.split('#')[ 0 ],
- },
- session,
- backupCreated: backupStatus.created
- }))
-}
-
-export async function waitForDataRoot(username: string): Promise {
- const session = getStore(sessionStore)
- const reference = session.program?.components.reference
- const EMPTY_CID = 'Qmc5m94Gu7z62RC8waSKkZUrCCBJPyHbkpmGzEePxy2oXJ'
-
- if (!reference) throw new Error('Program must be initialized to check for data root')
-
- let dataRoot = await reference.dataRoot.lookup(username)
-
- if (dataRoot.toString() !== EMPTY_CID) return
-
- return new Promise((resolve) => {
- const maxRetries = 50
- let attempt = 0
-
- const dataRootInterval = setInterval(async () => {
- dataRoot = await reference.dataRoot.lookup(username)
-
- if (dataRoot.toString() === EMPTY_CID && attempt < maxRetries) {
- attempt++
- return
- }
-
- clearInterval(dataRootInterval)
- resolve()
- }, 500)
- })
-}
diff --git a/src/lib/auth/backup.ts b/src/lib/auth/backup.ts
deleted file mode 100644
index 7f4a729..0000000
--- a/src/lib/auth/backup.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import * as odd from '@oddjs/odd'
-import type FileSystem from '@oddjs/odd/fs/index'
-
-export type BackupStatus = { created: boolean } | null
-
-export const setBackupStatus = async (fs: FileSystem, status: BackupStatus): Promise => {
- const backupStatusPath = odd.path.file('private', 'backup-status.json')
- await fs.write(backupStatusPath, new TextEncoder().encode(JSON.stringify(status)))
- await fs.publish()
-}
-
-export const getBackupStatus = async (fs: FileSystem): Promise => {
- const backupStatusPath = odd.path.file('private', 'backup-status.json')
-
- if (await fs.exists(backupStatusPath)) {
- const fileContent = await fs.read(backupStatusPath)
-
- try {
- return JSON.parse(
- new TextDecoder().decode(fileContent)
- ) as BackupStatus
- } catch (err) {
- console.warn(`Unable to load backup status: ${err.message || err}`)
- }
-
- return { created: false }
- } else {
- return { created: false }
- }
-}
diff --git a/src/lib/auth/linking.ts b/src/lib/auth/linking.ts
deleted file mode 100644
index 83957ab..0000000
--- a/src/lib/auth/linking.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type * as odd from '@oddjs/odd'
-import { get as getStore } from 'svelte/store'
-
-import { sessionStore } from '$lib/stores'
-
-
-export const createAccountLinkingConsumer = async (
- username: string
-): Promise => {
- const session = getStore(sessionStore)
- if (session.authStrategy) return session.authStrategy.accountConsumer(username)
-
- // Wait for program to be initialised
- return new Promise((resolve) => {
- sessionStore.subscribe(updatedState => {
- if (!updatedState.authStrategy) return
- const consumer = updatedState.authStrategy.accountConsumer(username)
- resolve(consumer)
- })
- })
-}
-
-export const createAccountLinkingProducer = async (
- username: string
-): Promise => {
- const session = getStore(sessionStore)
- return session.authStrategy.accountProducer(username)
-}
diff --git a/src/lib/init.ts b/src/lib/init.ts
index ca01290..56cca6b 100644
--- a/src/lib/init.ts
+++ b/src/lib/init.ts
@@ -1,82 +1,92 @@
-import * as odd from '@oddjs/odd'
-import { dev } from '$app/environment'
+// import { UCAN } from '@fission-codes/ucan'
+// import type { Capabilities } from '@fission-codes/ucan/dist/src/types'
+// import { RSASigner } from 'iso-signatures/signers/rsa'
+// import { DIDKey } from 'iso-did/key'
+import localforage from 'localforage'
-import { filesystemStore, sessionStore } from './stores'
-import { getBackupStatus, type BackupStatus } from '$lib/auth/backup'
-import { USERNAME_STORAGE_KEY, createDID } from '$lib/auth/account'
-import { oddNamespace } from '$lib/app-info'
+import { IDB_ACCOUNT_DID_LABEL, IDB_ACCOUNT_ID_LABEL, IDB_UCAN_LABEL } from '$lib/session'
+import { sessionStore } from '$lib/stores'
export const initialize = async (): Promise => {
try {
- let backupStatus: BackupStatus = null
+ const accountDid = await localforage.getItem(IDB_ACCOUNT_DID_LABEL)
+ const accountId = await localforage.getItem(IDB_ACCOUNT_ID_LABEL) as number
+ const ucan = await localforage.getItem(IDB_UCAN_LABEL)
- const program: odd.Program = await odd.program({
- namespace: oddNamespace,
- debug: dev
- })
+ // If there is no save accountDid or ucan, there's no active session
+ if (!accountDid || !ucan) {
+ sessionStore.set({
+ id: null,
+ username: null,
+ loading: false
+ })
+ return
+ }
- if (program.session) {
- // Authed
- backupStatus = await getBackupStatus(program.session.fs)
+ // const serverDid = await(
+ // await fetch('http://localhost:3000/api/v0/server-did')
+ // ).text()
+ // const audience = DIDKey.fromString(serverDid)
- let fullUsername = await program.components.storage.getItem(USERNAME_STORAGE_KEY) as string
+ // const idbPrivateKeyLabel = 'control-panel/v1/agent/signing-keypair'
- // If the user is migrating from a version odd-app-template before https://github.com/oddsdk/odd-app-template/pull/97/files#diff-a180510e798b8f833ebfdbe691c5ec4a1095076980d3e2388de29c849b2b8361R44,
- // their username won't contain a did, so we will need to manually append a DID and add it storage here
- if (!fullUsername) {
- const did = await createDID(program.components.crypto)
- fullUsername = `${program.session.username}#${did}`
- await program.components.storage.setItem(USERNAME_STORAGE_KEY, fullUsername)
- window.location.reload()
- }
+ // // TODO: This is using an old version of iso-signatures, @fission-codes/stack needs to be updated
+ // const principal = await RSASigner.generate()
- sessionStore.set({
- username: {
- full: fullUsername,
- hashed: program.session.username,
- trimmed: fullUsername.split('#')[0],
- },
- session: program.session,
- authStrategy: program.auth,
- program,
- loading: false,
- backupCreated: backupStatus.created
- })
+ // const keyPair = await localforage.getItem(idbPrivateKeyLabel)
- filesystemStore.set(program.session.fs)
+ // const ucan = await UCAN.create({
+ // issuer: principal,
+ // audience,
+ // ttl: 60, // A rough estimate that accounts for clock drift
+ // capabilities: ({
+ // [principal.did.toString()]: { 'capability/fetch': [{}] }
+ // } as unknown) as Capabilities
+ // })
- } else {
- // Not authed
- sessionStore.set({
- username: null,
- session: null,
- authStrategy: program.auth,
- program,
- loading: false,
- backupCreated: null
- })
- }
+ // const response = await fetch('http://localhost:3000/api/v0/capabilities', {
+ // method: 'GET',
+ // headers: {
+ // Accept: 'application/json',
+ // 'Content-Type': 'application/json',
+ // Authorization: `Bearer ${ucan.toString()}`
+ // }
+ // })
- } catch (error) {
- console.error(error)
+ // const ucan = await UCAN.create({
+ // issuer: DIDKey.fromString(accountDid),
+ // audience,
+ // ttl: 60, // A rough estimate that accounts for clock drift
+ // capabilities: ({
+ // [accountDid]: { 'account/info': [{}] }
+ // } as unknown) as Capabilities
+ // })
- switch (error) {
- case odd.ProgramError.InsecureContext:
- sessionStore.update(session => ({
- ...session,
- loading: false,
- error: 'Insecure Context'
- }))
- break
+ const response = await fetch(
+ `http://localhost:3000/api/v0/account/${accountDid}`,
+ {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${ucan.toString()}`
+ }
+ }
+ )
- case odd.ProgramError.UnsupportedBrowser:
- sessionStore.update(session => ({
- ...session,
- loading: false,
- error: 'Unsupported Browser'
- }))
- break
- }
+ const { username } = await response.json()
+ sessionStore.set({
+ id: accountId,
+ username,
+ loading: false,
+ })
+ } catch (error) {
+ sessionStore.set({
+ username: null,
+ loading: false,
+ })
+
+ console.error(error)
}
}
diff --git a/src/lib/session.ts b/src/lib/session.ts
index d6cb573..b9308c3 100644
--- a/src/lib/session.ts
+++ b/src/lib/session.ts
@@ -1,31 +1,11 @@
-import type * as odd from '@oddjs/odd'
-
-import { appName } from '$lib/app-info'
-
-type Username = {
- full: string
- hashed: string
- trimmed: string
-}
-
export type Session = {
- username: Username
- session: odd.Session | null
- authStrategy: odd.AuthenticationStrategy | null
- program: odd.Program
+ id?: number
+ username: string
loading: boolean
- backupCreated: boolean
- error?: SessionError
}
-type SessionError = 'Insecure Context' | 'Unsupported Browser'
+export const IDB_ACCOUNT_DID_LABEL = 'control-panel/v1/account/did'
-export const errorToMessage = (error: SessionError): string => {
- switch (error) {
- case 'Insecure Context':
- return `${appName} requires a secure context (HTTPS)`
+export const IDB_ACCOUNT_ID_LABEL = 'control-panel/v1/account/id'
- case 'Unsupported Browser':
- return `Your browser does not support ${appName}`
- }
-}
+export const IDB_UCAN_LABEL = 'control-panel/v1/ucan'
diff --git a/src/lib/stores.ts b/src/lib/stores.ts
index 50ba597..aa030f6 100644
--- a/src/lib/stores.ts
+++ b/src/lib/stores.ts
@@ -1,10 +1,8 @@
import { writable } from 'svelte/store'
import type { Writable } from 'svelte/store'
-import type FileSystem from '@oddjs/odd/fs/index'
import type { Maybe } from '$lib'
import { loadTheme } from '$lib/theme'
-import type { AccountSettings } from '$lib/account-settings'
import type { Notification } from '$lib/notifications'
import type { Session } from '$lib/session'
import type { Theme } from '$lib/theme'
@@ -18,23 +16,13 @@ import workflows from '$routes/workflows/lib/workflow-mocks'
export const themeStore: Writable = writable(loadTheme())
export const sessionStore: Writable = writable({
+ id: null,
username: null,
- session: null,
- authStrategy: null,
- program: null,
loading: true,
- backupCreated: null
})
-export const filesystemStore: Writable = writable(null)
-
export const notificationStore: Writable = writable([])
-export const accountSettingsStore: Writable = writable({
- avatar: null,
- loading: true,
-})
-
export const functionsStore: Writable = writable({
loading: false,
functions
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index a7246e3..11d44fa 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -10,10 +10,8 @@
checkIPFSConnection
} from '$lib/connections'
import subscribNetworkEvents from '$lib/network'
- import { addNotification } from '$lib/notifications'
import { sessionStore, themeStore } from '$lib/stores'
import { unsubscribeRPC } from '$lib/rpc'
- import { errorToMessage } from '$lib/session'
import { initialize } from '$lib/init'
import DataWidget from '$components/common/DataWidget.svelte'
import GlobalShortcutHandler from '$components/common/GlobalShortcutHandler.svelte'
@@ -30,20 +28,13 @@
$: isActivity = $page.route.id === '/activity'
let screenSize: number
- const unsubscribeSessionStore = sessionStore.subscribe(session => {
- if (session.error) {
- const message = errorToMessage(session.error)
- addNotification({ msg: message, type: 'error' })
- }
- })
-
const init = async () => {
await initialize()
// Redirect to home if not logged in
if (
- window.location.href !== window.location.origin ||
- (!window.location.href.includes('onboarding') && !$sessionStore.session)
+ window.location.href !== window.location.origin &&
+ !$sessionStore.username
) {
goto('/')
}
@@ -67,7 +58,6 @@
onDestroy(() => {
unsubscribeRPC()
- unsubscribeSessionStore()
})
@@ -89,10 +79,12 @@
{:else}
- {#if isHome && screenSize >= 768}
-
- {:else if !isHome}
-
+ {#if !$page.route.id.includes('onboarding')}
+ {#if isHome && screenSize >= 768}
+
+ {:else if !isHome}
+
+ {/if}
{/if}
- {#if isHome && $sessionStore.session}
+ {#if isHome && $sessionStore.username}
{/if}
- {#if $sessionStore.session}
+ {#if $sessionStore.username}
{/if}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 0464cec..3dee0d7 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -12,7 +12,7 @@
})
-{#if $sessionStore?.session}
+{#if $sessionStore?.username}
{:else}
diff --git a/src/routes/backup/+page.svelte b/src/routes/backup/+page.svelte
deleted file mode 100644
index f2a3056..0000000
--- a/src/routes/backup/+page.svelte
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-{#if view === 'backup'}
-
-{:else if view === 'are-you-sure'}
-
-{/if}
diff --git a/src/routes/delegate-account/+page.svelte b/src/routes/delegate-account/+page.svelte
deleted file mode 100644
index c9fa19d..0000000
--- a/src/routes/delegate-account/+page.svelte
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-{#if view === 'connect-backup-device'}
-
-{:else if view === 'delegate-account'}
-
-{/if}
diff --git a/src/routes/link-device/+page.svelte b/src/routes/link-device/+page.svelte
deleted file mode 100644
index d31ea81..0000000
--- a/src/routes/link-device/+page.svelte
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-{#if view === 'link-device'}
-
-{:else if view === 'load-filesystem'}
-
-{/if}
diff --git a/src/routes/onboarding/details/+page.svelte b/src/routes/onboarding/details/+page.svelte
index e347821..c50d57a 100644
--- a/src/routes/onboarding/details/+page.svelte
+++ b/src/routes/onboarding/details/+page.svelte
@@ -2,6 +2,7 @@
import { goto } from '$app/navigation'
import { addNotification } from '$lib/notifications'
+ import { sessionStore } from '$lib/stores'
import Input from '$components/form/Input.svelte'
import StarMedium from '$components/icons/StarMedium.svelte'
import StarSmall from '$components/icons/StarSmall.svelte'
@@ -90,7 +91,7 @@
-
+
@@ -99,6 +100,10 @@
+
+
+ Onboarding member #{$sessionStore.id}
+