fix: multiple settings objects created for 1 user

due to these multiple objects reset password wasn't working because
only the latest one would be encrypted with the new password
but all previous objects would require decryption
which resulted in a block while syncing
This commit is contained in:
thecodrr
2021-02-26 17:33:46 +05:00
parent c0e78aa5c9
commit dd2a065be7
5 changed files with 30 additions and 26 deletions

View File

@@ -1,5 +1,6 @@
import { EV, EVENTS } from "../common"; import { EV, EVENTS } from "../common";
import id from "../utils/id"; import id from "../utils/id";
import setManipulator from "../utils/set";
class Settings { class Settings {
/** /**
@@ -8,13 +9,7 @@ class Settings {
*/ */
constructor(db) { constructor(db) {
this._db = db; this._db = db;
this._settings = { this._settings = undefined;
type: "settings",
id: id(),
pins: [],
dateEdited: 0,
dateCreated: Date.now(),
};
} }
get raw() { get raw() {
@@ -22,23 +17,28 @@ class Settings {
} }
async merge(item) { async merge(item) {
this._settings = { // TODO if (this.settings.dateEdited > (await this._db.lastSynced())) {
...this._settings, // this._settings.pins = setManipulator.union(
...item, // this._settings.pins,
}; // item.pins
await this._db.context.write("settings", this._settings); // );
// }
this._settings = item;
await this._db.context.write("settings", item);
} }
async init() { async init() {
var settings = await this._db.context.read("settings"); var settings = await this._db.context.read("settings");
if (!settings) await this._db.context.write("settings", this._settings); this._settings = settings;
else this._settings = settings;
EV.subscribe(EVENTS.userLoggedOut, () => { EV.subscribe(EVENTS.userLoggedOut, () => {
this._settings = undefined;
});
EV.subscribe(EVENTS.userSignedUp, () => {
this._settings = { this._settings = {
type: "settings", type: "settings",
id: id(), id: id(),
pins: [], pins: [],
dateEdited: 0, dateEdited: Date.now(),
dateCreated: Date.now(), dateCreated: Date.now(),
}; };
}); });
@@ -66,6 +66,7 @@ class Settings {
} }
get pins() { get pins() {
if (!this._settings) return [];
return this._settings.pins.reduce((prev, pin) => { return this._settings.pins.reduce((prev, pin) => {
let item; let item;
if (pin.type === "notebook") { if (pin.type === "notebook") {

View File

@@ -24,10 +24,10 @@ class Collector {
}; };
} }
async collect(lastSyncedTimestamp, force) { async collect(lastSyncedTimestamp) {
this._lastSyncedTimestamp = lastSyncedTimestamp; this._lastSyncedTimestamp = lastSyncedTimestamp;
this.key = await this._db.user.getEncryptionKey(); this.key = await this._db.user.getEncryptionKey();
this.force = force;
return { return {
notes: await this._collect(this._db.notes.raw), notes: await this._collect(this._db.notes.raw),
notebooks: await this._collect(this._db.notebooks.raw), notebooks: await this._collect(this._db.notebooks.raw),
@@ -44,11 +44,9 @@ class Collector {
} }
_collect(array) { _collect(array) {
if (this.force) {
return Promise.all(array.map(this._map));
}
return Promise.all( return Promise.all(
array.reduce((prev, item) => { array.reduce((prev, item) => {
if (!item) return prev;
if (item.dateEdited > this._lastSyncedTimestamp || item.migrated) if (item.dateEdited > this._lastSyncedTimestamp || item.migrated)
prev.push(this._map(item)); prev.push(this._map(item));
return prev; return prev;

View File

@@ -63,12 +63,14 @@ export default class Sync {
} }
async start(full, force) { async start(full, force) {
if (force) await this._db.context.write("lastSynced", 0);
let { lastSynced, token } = await this._performChecks(); let { lastSynced, token } = await this._performChecks();
if (full) var serverResponse = await this._fetch(lastSynced, token); if (full) var serverResponse = await this._fetch(lastSynced, token);
// we prepare local data before merging so we always have correct data // we prepare local data before merging so we always have correct data
const data = await this._collector.collect(lastSynced, force); const data = await this._collector.collect(lastSynced);
if (full) { if (full) {
// merge the server response // merge the server response

View File

@@ -39,6 +39,7 @@ class UserManager {
password: hashedPassword, password: hashedPassword,
client_id: "notesnook", client_id: "notesnook",
}); });
EV.publish(EVENTS.userSignedUp);
return await this.login(email, password, true, hashedPassword); return await this.login(email, password, true, hashedPassword);
} }
@@ -198,7 +199,7 @@ class UserManager {
if (!token) return; if (!token) return;
// we hash the passwords beforehand // we hash the passwords beforehand
const { email } = await this.getUser(); const { email, salt } = await this.getUser();
var hashedData = {}; var hashedData = {};
if (data.old_password) if (data.old_password)
hashedData.old_password = await this._db.context.hash( hashedData.old_password = await this._db.context.hash(
@@ -223,13 +224,14 @@ class UserManager {
type, type,
{ newPassword: data.new_password }, { newPassword: data.new_password },
async () => { async () => {
const key = await this.getEncryptionKey(); await this._db.sync(true);
const { email } = await this.getUser();
await this._db.context.deriveCryptoKey(`_uk_@${email}`, { await this._db.context.deriveCryptoKey(`_uk_@${email}`, {
password: data.new_password, password: data.new_password,
salt: key.salt, salt,
}); });
await this._db.sync(true, true);
await this._db.sync(false, true);
} }
); );
return true; return true;

View File

@@ -25,6 +25,7 @@ export const EVENTS = {
userLoggedIn: "user:loggedIn", userLoggedIn: "user:loggedIn",
userLoggedOut: "user:loggedOut", userLoggedOut: "user:loggedOut",
userFetched: "user:fetched", userFetched: "user:fetched",
userSignedUp: "user:signedUp",
databaseSyncRequested: "db:syncRequested", databaseSyncRequested: "db:syncRequested",
databaseMigrated: "db:migrated", databaseMigrated: "db:migrated",
databaseUpdated: "db:updated", databaseUpdated: "db:updated",