feat: implement SNJS backup file password retrieval

This commit is contained in:
Baptiste Grob
2021-01-28 15:28:55 +01:00
parent 1576da01c4
commit d4f02a124d
7 changed files with 74 additions and 113 deletions

View File

@@ -342,13 +342,6 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
}
}
async submitImportPassword() {
await this.performImport(
this.getState().importData.data,
this.getState().importData.password
);
}
showRegister() {
this.setFormDataState({
showRegister: true
@@ -384,73 +377,52 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
if (data.version || data.auth_params || data.keyParams) {
const version = data.version || data.keyParams?.version || data.auth_params?.version;
if (
!this.application!.protocolService!.supportedVersions().includes(version)
this.application.protocolService.supportedVersions().includes(version)
) {
await this.setState({ importData: null });
alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION });
return;
}
if (data.keyParams || data.auth_params) {
await this.setState({
importData: {
...this.getState().importData,
requestPassword: true,
data,
}
});
const element = document.getElementById(
ELEMENT_ID_IMPORT_PASSWORD_INPUT
);
if (element) {
element.scrollIntoView(false);
}
await this.performImport(data);
} else {
await this.performImport(data, undefined);
await this.setState({ importData: null });
void alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION });
}
} else {
await this.performImport(data, undefined);
await this.performImport(data);
}
}
async performImport(data: BackupFile, password?: string) {
if (!(await this.application.authorizeFileImport())) {
return;
}
async performImport(data: BackupFile) {
await this.setState({
importData: {
...this.getState().importData,
loading: true
}
});
const result = await this.application!.importData(
data,
password
);
const result = await this.application.importData(data);
this.setState({
importData: null
});
if ('error' in result) {
this.application!.alertService!.alert(
result.error
);
if (!result) {
return;
} else if ('error' in result) {
void alertDialog({
text: result.error
});
} else if (result.errorCount) {
const message = StringImportError(result.errorCount);
this.application!.alertService!.alert(
message
);
void alertDialog({
text: StringImportError(result.errorCount)
});
} else {
this.application!.alertService!.alert(
STRING_IMPORT_SUCCESS
);
void alertDialog({
text: STRING_IMPORT_SUCCESS
});
}
}
async downloadDataArchive() {
this.application!.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted);
this.application.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted);
}
notesAndTagsCount() {
return this.application!.getItems(
return this.application.getItems(
[
ContentType.Note,
ContentType.Tag

View File

@@ -10,7 +10,6 @@ import {
UuidString,
SyncOpStatus,
PrefKey,
Challenge,
} from '@standardnotes/snjs';
import { WebApplication } from '@/ui_models/application';
import { Editor } from '@/ui_models/editor';
@@ -28,6 +27,11 @@ export enum AppStateEvent {
WindowDidBlur,
}
export type PanelResizedData = {
panel: string;
collapsed: boolean;
}
export enum EventSource {
UserInteraction,
Script,
@@ -392,10 +396,11 @@ export class AppState {
}
panelDidResize(name: string, collapsed: boolean) {
this.notifyEvent(AppStateEvent.PanelResized, {
const data: PanelResizedData = {
panel: name,
collapsed: collapsed,
});
};
this.notifyEvent(AppStateEvent.PanelResized, data);
}
editorDidFocus(eventSource: EventSource) {

View File

@@ -28,7 +28,7 @@
application='self.application'
)
challenge-modal(
ng-repeat="challenge in self.state.challenges track by challenge.id"
ng-repeat="challenge in self.challenges track by challenge.id"
class="sk-modal"
application="self.application"
challenge="challenge"

View File

@@ -2,8 +2,8 @@ import { RootScopeMessages } from './../../messages';
import { WebDirective } from '@/types';
import { getPlatformString } from '@/utils';
import template from './application-view.pug';
import { AppStateEvent } from '@/ui_models/app_state';
import { ApplicationEvent, Challenge } from '@standardnotes/snjs';
import { AppStateEvent, PanelResizedData } from '@/ui_models/app_state';
import { ApplicationEvent, Challenge, removeFromArray } from '@standardnotes/snjs';
import {
PANEL_NAME_NOTES,
PANEL_NAME_TAGS
@@ -18,18 +18,20 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
ready?: boolean,
needsUnlock?: boolean,
appClass: string,
challenges: Challenge[]
}> {
private $location?: ng.ILocationService
private $rootScope?: ng.IRootScopeService
public platformString: string
private notesCollapsed = false
private tagsCollapsed = false
/**
* To prevent stale state reads (setState is async),
* challenges is a mutable array
*/
private challenges: Challenge[] = [];
/* @ngInject */
constructor(
$location: ng.ILocationService,
$rootScope: ng.IRootScopeService,
private $location: ng.ILocationService,
private $rootScope: ng.IRootScopeService,
$timeout: ng.ITimeoutService
) {
super($timeout);
@@ -43,8 +45,8 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
}
deinit() {
this.$location = undefined;
this.$rootScope = undefined;
(this.$location as unknown) = undefined;
(this.$rootScope as unknown) = undefined;
(this.application as unknown) = undefined;
window.removeEventListener('dragover', this.onDragOver, true);
window.removeEventListener('drop', this.onDragDrop, true);
@@ -66,23 +68,22 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
}
async loadApplication() {
this.application!.componentManager!.setDesktopManager(
this.application!.getDesktopService()
this.application.componentManager.setDesktopManager(
this.application.getDesktopService()
);
await this.application!.prepareForLaunch({
await this.application.prepareForLaunch({
receiveChallenge: async (challenge) => {
this.setState({
challenges: this.state.challenges.concat(challenge)
this.$timeout(() => {
this.challenges.push(challenge);
});
}
});
await this.application!.launch();
await this.application.launch();
}
public removeChallenge(challenge: Challenge) {
this.setState({
challenges: this.state.challenges.filter(c => c.id !== challenge.id)
public async removeChallenge(challenge: Challenge) {
this.$timeout(() => {
removeFromArray(this.challenges, challenge);
});
}
@@ -90,7 +91,7 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
super.onAppStart();
this.setState({
ready: true,
needsUnlock: this.application!.hasPasscode()
needsUnlock: this.application.hasPasscode()
});
}
@@ -101,7 +102,7 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
}
onUpdateAvailable() {
this.$rootScope!.$broadcast(RootScopeMessages.NewUpdateAvailable);
this.$rootScope.$broadcast(RootScopeMessages.NewUpdateAvailable);
}
/** @override */
@@ -119,21 +120,22 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
}
/** @override */
async onAppStateEvent(eventName: AppStateEvent, data?: any) {
async onAppStateEvent(eventName: AppStateEvent, data?: unknown) {
if (eventName === AppStateEvent.PanelResized) {
if (data.panel === PANEL_NAME_NOTES) {
this.notesCollapsed = data.collapsed;
const { panel, collapsed } = data as PanelResizedData;
if (panel === PANEL_NAME_NOTES) {
this.notesCollapsed = collapsed;
}
if (data.panel === PANEL_NAME_TAGS) {
this.tagsCollapsed = data.collapsed;
if (panel === PANEL_NAME_TAGS) {
this.tagsCollapsed = collapsed;
}
let appClass = "";
if (this.notesCollapsed) { appClass += "collapsed-notes"; }
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
this.setState({ appClass });
} else if (eventName === AppStateEvent.WindowDidFocus) {
if (!(await this.application!.isLocked())) {
this.application!.sync();
if (!(await this.application.isLocked())) {
this.application.sync();
}
}
}
@@ -149,29 +151,29 @@ class ApplicationViewCtrl extends PureViewCtrl<unknown, {
}
onDragOver(event: DragEvent) {
if (event.dataTransfer!.files.length > 0) {
if (event.dataTransfer?.files.length) {
event.preventDefault();
}
}
onDragDrop(event: DragEvent) {
if (event.dataTransfer!.files.length > 0) {
if (event.dataTransfer?.files.length) {
event.preventDefault();
this.application!.alertService!.alert(
STRING_DEFAULT_FILE_ERROR
);
void alertDialog({
text: STRING_DEFAULT_FILE_ERROR
});
}
}
async handleDemoSignInFromParams() {
if (
this.$location!.search().demo === 'true' &&
this.$location.search().demo === 'true' &&
!this.application.hasAccount()
) {
await this.application!.setHost(
await this.application.setHost(
'https://syncing-server-demo.standardnotes.org'
);
this.application!.signIn(
this.application.signIn(
'demo@standardnotes.org',
'password',
);