fix: Auth persistence to localStorage (#3078)

* fix: user, team, and policies should be persisted to localStorage for faster boot

* capture instead of ignore errors
This commit is contained in:
Tom Moor
2022-02-08 21:14:15 -08:00
committed by GitHub
parent aa09dc39fb
commit 156b47b1b5
2 changed files with 35 additions and 10 deletions

View File

@@ -22,7 +22,7 @@ export default class BaseModel {
try { try {
// ensure that the id is passed if the document has one // ensure that the id is passed if the document has one
if (!params) { if (!params) {
params = this.toJS(); params = this.toAPI();
} }
const model = await this.store.save({ ...params, id: this.id }); const model = await this.store.save({ ...params, id: this.id });
@@ -30,7 +30,7 @@ export default class BaseModel {
// if saving is successful set the new values on the model itself // if saving is successful set the new values on the model itself
set(this, { ...params, ...model }); set(this, { ...params, ...model });
this.persistedAttributes = this.toJS(); this.persistedAttributes = this.toAPI();
return model; return model;
} finally { } finally {
@@ -40,7 +40,7 @@ export default class BaseModel {
updateFromJson = (data: any) => { updateFromJson = (data: any) => {
set(this, data); set(this, data);
this.persistedAttributes = this.toJS(); this.persistedAttributes = this.toAPI();
}; };
fetch = (options?: any) => { fetch = (options?: any) => {
@@ -64,15 +64,38 @@ export default class BaseModel {
}; };
/** /**
* Returns a plain object representation of the model * Returns a plain object representation of fields on the model for
* persistence to the server API
* *
* @returns {Record<string, any>} * @returns {Record<string, any>}
*/ */
toJS = (): Record<string, any> => { toAPI = (): Record<string, any> => {
const fields = getFieldsForModel(this); const fields = getFieldsForModel(this);
return pick(this, fields) || []; return pick(this, fields) || [];
}; };
/**
* Returns a plain object representation of all the properties on the model
* overrides the inbuilt toJSON method to avoid attempting to serialize store
*
* @returns {Record<string, any>}
*/
toJSON() {
const output: Partial<typeof this> = {};
for (const property in this) {
if (
// eslint-disable-next-line no-prototype-builtins
this.hasOwnProperty(property) &&
!["persistedAttributes", "store", "isSaving"].includes(property)
) {
output[property] = this[property];
}
}
return output;
}
/** /**
* Returns a boolean indicating if the model has changed since it was last * Returns a boolean indicating if the model has changed since it was last
* persisted to the server * persisted to the server
@@ -80,7 +103,7 @@ export default class BaseModel {
* @returns boolean true if unsaved * @returns boolean true if unsaved
*/ */
isDirty(): boolean { isDirty(): boolean {
const attributes = this.toJS(); const attributes = this.toAPI();
if (Object.keys(attributes).length === 0) { if (Object.keys(attributes).length === 0) {
console.warn("Checking dirty on model with no @Field decorators"); console.warn("Checking dirty on model with no @Field decorators");

View File

@@ -68,19 +68,21 @@ export default class AuthStore {
try { try {
data = JSON.parse(localStorage.getItem(AUTH_STORE) || "{}"); data = JSON.parse(localStorage.getItem(AUTH_STORE) || "{}");
} catch (_) { } catch (err) {
// no-op Safari private mode Sentry.captureException(err);
} }
this.rehydrate(data); this.rehydrate(data);
// persists this entire store to localstorage whenever any keys are changed // persists this entire store to localstorage whenever any keys are changed
autorun(() => { autorun(() => {
try { try {
localStorage.setItem(AUTH_STORE, this.asJson); localStorage.setItem(AUTH_STORE, this.asJson);
} catch (_) { } catch (err) {
// no-op Safari private mode Sentry.captureException(err);
} }
}); });
// listen to the localstorage value changing in other tabs to react to // listen to the localstorage value changing in other tabs to react to
// signin/signout events in other tabs and follow suite. // signin/signout events in other tabs and follow suite.
window.addEventListener("storage", (event) => { window.addEventListener("storage", (event) => {