-
Notifications
You must be signed in to change notification settings - Fork 1
Mysky autologin stored settings and logout #188
Changes from 11 commits
7d2fe37
6a03865
3ef9ad7
5e60df4
6d10fe5
a56b4fe
3db1e6a
c1a7812
a8e518d
181fd70
eae675b
10a9209
3d3ce52
cce3dbb
6a19718
bc5065a
d922f2d
1815b87
ccbf35f
4034089
a45f435
50be38e
4e10f5c
fe13a7b
d5b79d1
1b44334
21a0e4b
61602fb
49eebcc
5b2f738
7a76de1
307b83a
58d6196
f9d0b59
f441ee5
c951e5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,7 @@ import { | |
import { MySky, SkynetClient } from "skynet-js"; | ||
|
||
import { hashWithSalt } from "../src/crypto"; | ||
import { login, register } from "../src/portal-account"; | ||
import { checkStoredSeed, EMAIL_STORAGE_KEY, SEED_STORAGE_KEY } from "../src/mysky"; | ||
import { checkStoredSeed, EMAIL_STORAGE_KEY, PORTAL_LOGIN_COMPLETE_SENTINEL_KEY, SEED_STORAGE_KEY } from "../src/mysky"; | ||
import { | ||
getPermissionsProviderUrl, | ||
relativePermissionsDisplayUrl, | ||
|
@@ -32,6 +31,9 @@ let parentConnection: Connection | null = null; | |
|
||
// Set value of dev on load. | ||
let dev = false; | ||
/// #if ENV == 'dev' | ||
dev = true; | ||
/// #endif | ||
|
||
// ====== | ||
// Events | ||
|
@@ -65,10 +67,6 @@ window.onerror = function (error: any) { | |
// TODO: Wrap in a try-catch block? Does onerror handler catch thrown errors? | ||
// Code that runs on page load. | ||
window.onload = () => { | ||
/// #if ENV == 'dev' | ||
dev = true; | ||
/// #endif | ||
|
||
void init(); | ||
}; | ||
|
||
|
@@ -117,6 +115,9 @@ async function requestLoginAccess(permissions: Permission[]): Promise<[boolean, | |
// Save the seed and email in local storage. | ||
saveSeedAndEmail(seed, email); | ||
|
||
// Wait for Main MySky to login successfully. | ||
await waitForMySkyPortalLogin(); | ||
|
||
// Pass in any request permissions and get a permissions response. | ||
const permissionsResponse = await getPermissions(seed, permissions); | ||
|
||
|
@@ -156,12 +157,7 @@ async function checkBrowserSupported(): Promise<void> { | |
* then we display the signin-connect page where the user may connect his email | ||
* on signin. | ||
* | ||
* 5. If we got the email, then we register/login to set the JWT cookie. | ||
* | ||
* 6. If the user provided a new email at some point, then we save it in user | ||
* settings, after having successfully connected to a portal account. | ||
* | ||
* (7. We return the seed and email and save them in storage in another | ||
* (5. We return the seed and email and save them in storage in another | ||
* function, which triggers Main MySky's storage listener.) | ||
* | ||
* @returns - The seed and email. | ||
|
@@ -208,16 +204,6 @@ async function getSeedAndEmail(): Promise<[Uint8Array, string | null]> { | |
} | ||
} | ||
|
||
// Register/login. | ||
if (email) { | ||
await connectToPortalAccount(seed, email); | ||
} | ||
|
||
// TODO: Save the new provided email in user settings. | ||
if (emailProvidedByUser) { | ||
await saveEmailInSettings(); | ||
} | ||
|
||
return [seed, email]; | ||
} | ||
|
||
|
@@ -280,39 +266,6 @@ async function getPermissions(seed: Uint8Array, permissions: Permission[]): Prom | |
return permissionsResponse; | ||
} | ||
|
||
/** | ||
* Connects to a portal account by either registering or logging in to an | ||
* existing account. The resulting cookie will be set on the MySky domain and | ||
* takes effect in Main MySky immediate. | ||
* | ||
* NOTE: Main MySky will register "auto re-login"; we don't have to do that | ||
* here. | ||
* | ||
* @param seed - The user seed. | ||
* @param email - The user email. | ||
*/ | ||
async function connectToPortalAccount(seed: Uint8Array, email: string): Promise<void> { | ||
// Register and get the JWT cookie. | ||
// | ||
// Make requests to login and register in parallel. At most one can succeed, | ||
// and this saves a lot of time. | ||
try { | ||
await Promise.any([register(client, seed, email), login(client, seed, email)]); | ||
} catch (e) { | ||
throw new Error(`Could not register or login: ${e}`); | ||
} | ||
} | ||
|
||
// TODO | ||
/** | ||
* If the email was provided by the user, save it in user settings. | ||
* | ||
* @returns - An empty promise. | ||
*/ | ||
async function saveEmailInSettings(): Promise<void> { | ||
return; | ||
} | ||
|
||
/** | ||
* Gets the user's seed provider display URL if set, or the default. | ||
* | ||
|
@@ -494,6 +447,26 @@ async function setupAndRunDisplay<T>(displayUrl: string, methodName: string, ... | |
}); | ||
} | ||
|
||
/** | ||
* Waits for portal login on Main MySky to complete. | ||
*/ | ||
async function waitForMySkyPortalLogin(): Promise<void> { | ||
return new Promise((resolve, reject) => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this might block forever, that's ok right? would've expected to see a timeout mechanism of sorts here |
||
window.addEventListener("storage", async ({ key, newValue }: StorageEvent) => { | ||
if (key !== PORTAL_LOGIN_COMPLETE_SENTINEL_KEY) { | ||
return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so this makes it so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we only want the promise to resolve when the right storage key is encountered. Any other storage key shouldn't trigger a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No! 😅 We don't want login to fail if a different key is set for whatever reason. If there is another storage event listener for that key, it will also be triggered. Here, we are only interested in the specific key we are listening for. |
||
} | ||
|
||
// Check for errors from Main MySky. | ||
if (newValue !== "") { | ||
reject(newValue); | ||
} | ||
|
||
resolve(); | ||
}) | ||
); | ||
} | ||
|
||
// ======= | ||
// Helpers | ||
// ======= | ||
|
@@ -510,8 +483,9 @@ async function catchError(errorMsg: string): Promise<void> { | |
|
||
/** | ||
* Stores the root seed and email in local storage. This triggers the storage | ||
* event listener in the main invisible MySky frame. Main MySky needs the email | ||
* so that it can login again when the JWT cookie expires. | ||
* event listener in the main invisible MySky frame. This switches to the | ||
* preferred portal, registers or logs in to the portal account and sets up | ||
* login again when the JWT cookie expires. See `setUpStorageEventListener`. | ||
* | ||
* NOTE: If ENV == 'dev' the seed is salted before storage. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit
looks kind of weird to be naming anasync
functionwaitFor
because you don't necessarily await it