Merge pull request #155 from Mikunj/password-clear-database

Allow resetting database from password view.
pull/159/head
sachaaaaa 6 years ago committed by GitHub
commit 7e583499f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1100,7 +1100,7 @@
},
"deleteAllDataBody": {
"message":
"You are about to delete all of this application's saved account information, including all contacts and all messages. You can always link with your mobile device again, but that will not restore deleted messages.",
"You are about to delete all of this application's saved account information, including all contacts and all messages. You can always register with your seed again, but that will not restore deleted messages.",
"description":
"Text describing what exactly will happen if the user clicks the button to delete all data"
},
@ -1777,6 +1777,12 @@
"unlock": {
"message": "Unlock"
},
"resetDatabase": {
"message": "Reset Database",
"description":
"A button action that the user can click to reset the database"
},
"setPassword": {
"message": "Set Password",
"description": "Button action that the user can click to set a password"

@ -643,6 +643,15 @@ let db;
let filePath;
let indexedDBPath;
function _initializePaths(configDir) {
indexedDBPath = path.join(configDir, 'IndexedDB');
const dbDir = path.join(configDir, 'sql');
mkdirp.sync(dbDir);
filePath = path.join(dbDir, 'db.sqlite');
}
async function initialize({ configDir, key }) {
if (db) {
throw new Error('Cannot initialize more than once!');
@ -655,12 +664,7 @@ async function initialize({ configDir, key }) {
throw new Error('initialize: key` is required!');
}
indexedDBPath = path.join(configDir, 'IndexedDB');
const dbDir = path.join(configDir, 'sql');
mkdirp.sync(dbDir);
filePath = path.join(dbDir, 'db.sqlite');
_initializePaths(configDir);
const sqlInstance = await openDatabase(filePath);
const promisified = promisify(sqlInstance);
@ -686,11 +690,15 @@ async function close() {
await dbRef.close();
}
async function removeDB() {
async function removeDB(configDir = null) {
if (db) {
throw new Error('removeDB: Cannot erase database when it is open!');
}
if (!filePath && configDir) {
_initializePaths(configDir);
}
rimraf.sync(filePath);
}

@ -21,8 +21,9 @@
'click .cancel': 'onCancel',
'click .delete-all-data': 'onDeleteAllData',
},
initialize() {
initialize(onClear = null) {
this.step = CLEAR_DATA_STEPS.CHOICE;
this.onClear = onClear;
},
onCancel() {
this.remove();
@ -35,21 +36,25 @@
await this.clearAllData();
},
async clearAllData() {
try {
await Logs.deleteAll();
if (this.onClear) {
this.onClear();
} else {
try {
await Logs.deleteAll();
await window.Signal.Data.removeAll();
await window.Signal.Data.close();
await window.Signal.Data.removeDB();
await window.Signal.Data.removeAll();
await window.Signal.Data.close();
await window.Signal.Data.removeDB();
await window.Signal.Data.removeOtherData();
} catch (error) {
window.log.error(
'Something went wrong deleting all data:',
error && error.stack ? error.stack : error
);
await window.Signal.Data.removeOtherData();
} catch (error) {
window.log.error(
'Something went wrong deleting all data:',
error && error.stack ? error.stack : error
);
}
window.restart();
}
window.restart();
},
render_attributes() {
return {

@ -9,19 +9,25 @@
window.Whisper = window.Whisper || {};
const MIN_LOGIN_TRIES = 3;
Whisper.PasswordView = Whisper.View.extend({
className: 'password full-screen-flow standalone-fullscreen',
templateName: 'password',
events: {
'click #unlock-button': 'onLogin',
'click #reset-button': 'onReset',
},
initialize() {
this.errorCount = 0;
this.render();
},
render_attributes() {
return {
title: i18n('passwordViewTitle'),
buttonText: i18n('unlock'),
resetText: i18n('resetDatabase'),
showReset: this.errorCount >= MIN_LOGIN_TRIES,
};
},
async onLogin() {
@ -31,11 +37,24 @@
try {
await window.onLogin(trimmed);
} catch (e) {
// Increment the error counter and show the button if necessary
this.errorCount += 1;
if (this.errorCount >= MIN_LOGIN_TRIES) {
this.render();
}
this.setError(`Error: ${e}`);
}
},
setError(string) {
this.$('.error').text(string);
},
onReset() {
const clearDataView = new window.Whisper.ClearDataView(() => {
window.resetDatabase();
});
clearDataView.render();
this.$el.append(clearDataView.el);
},
});
})();

@ -747,6 +747,18 @@ function getDefaultSQLKey() {
return key;
}
async function removeDB() {
const userDir = await getRealPath(app.getPath('userData'));
sql.removeDB(userDir);
try {
userConfig.remove();
ephemeralConfig.remove();
} catch (e) {
console.warn('Remove DB: Failed to remove configs.', e);
}
}
async function showMainWindow(sqlKey) {
const userDataPath = await getRealPath(app.getPath('userData'));
@ -939,6 +951,12 @@ ipc.on('restart', () => {
app.quit();
});
ipc.on('resetDatabase', async () => {
await removeDB();
app.relaunch();
app.quit();
});
ipc.on('set-auto-hide-menu-bar', (event, autoHide) => {
if (mainWindow) {
mainWindow.setAutoHideMenuBar(autoHide);

@ -24,14 +24,55 @@
<input class='form-control' type='password' id='passPhrase' placeholder='Password' autocomplete='off' spellcheck='false' />
<a class='button' id='unlock-button'>{{ buttonText }}</a>
<div class='error'></div>
{{ #showReset }}
<div class='reset'>
<a id='reset-button'>{{ resetText }}</a>
</div>
{{ /showReset }}
</div>
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='clear-data'>
{{#isStep1}}
<div class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon alert-outline-red'></span>
<div class='header'>{{ header }}</div>
<div class='body-text-wide'>{{ body }}</div>
</div>
<div class='nav'>
<div>
<a class='button neutral cancel'>{{ cancelButton }}</a>
<a class='button destructive delete-all-data'>{{ deleteButton }}</a>
</div>
</div>
</div>
</div>
{{/isStep1}}
{{#isStep2}}
<div id='step3' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon delete'></span>
<div class='header'>{{ deleting }}</div>
</div>
<div class='progress'>
<div class='bar-container'>
<div class='bar progress-bar progress-bar-striped active'></div>
</div>
</div>
</div>
</div>
{{/isStep2}}
</script>
<script type='text/javascript' src='js/components.js'></script>
<script type='text/javascript' src='js/views/whisper_view.js'></script>
<script type='text/javascript' src='js/views/password_view.js'></script>
<script type='text/javascript' src='js/views/clear_data_view.js'></script>
</head>
<body>
<div class='app-loading-screen'>

@ -26,6 +26,10 @@ window.getAppInstance = () => config.appInstance;
window.passwordUtil = require('./app/password_util');
window.resetDatabase = () => {
window.log.info('reset database');
ipcRenderer.send('resetDatabase');
};
window.onLogin = passPhrase =>
new Promise((resolve, reject) => {
ipcRenderer.once('password-window-login-response', (event, error) => {

@ -26,4 +26,25 @@
font-size: 16px;
margin-top: 1em;
}
.reset {
font-size: 15px;
margin-top: 1em;
cursor: pointer;
user-select: none;
a {
color: #78be20;
font-weight: bold;
}
}
.overlay {
color: $color-dark-05;
background: $color-dark-85;
.step {
padding: 0;
}
}
}

Loading…
Cancel
Save