feat: implement SNJS backup file password retrieval
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user