mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-25 12:15:18 +01:00
Added import for lastpass csv. Username no longer required.
This commit is contained in:
parent
49921f7355
commit
9aa62e748c
@ -21,10 +21,6 @@
|
|||||||
del: { method: 'DELETE', params: { id: '@id' } }
|
del: { method: 'DELETE', params: { id: '@id' } }
|
||||||
});
|
});
|
||||||
|
|
||||||
_service.ciphers = $resource(_apiUri + '/ciphers/:id', {}, {
|
|
||||||
putMany: { url: _apiUri + '/ciphers/many', method: 'PUT', params: {} }
|
|
||||||
});
|
|
||||||
|
|
||||||
_service.accounts = $resource(_apiUri + '/accounts', {}, {
|
_service.accounts = $resource(_apiUri + '/accounts', {}, {
|
||||||
registerToken: { url: _apiUri + '/accounts/register-token', method: 'POST', params: {} },
|
registerToken: { url: _apiUri + '/accounts/register-token', method: 'POST', params: {} },
|
||||||
register: { url: _apiUri + '/accounts/register', method: 'POST', params: {} },
|
register: { url: _apiUri + '/accounts/register', method: 'POST', params: {} },
|
||||||
@ -36,7 +32,8 @@
|
|||||||
getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} },
|
getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} },
|
||||||
putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'PUT', params: {} },
|
putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'PUT', params: {} },
|
||||||
postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} },
|
postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} },
|
||||||
putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'PUT', params: {} }
|
putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'PUT', params: {} },
|
||||||
|
'import': { url: _apiUri + '/accounts/import', method: 'POST', params: {} }
|
||||||
});
|
});
|
||||||
|
|
||||||
_service.auth = $resource(_apiUri + '/auth', {}, {
|
_service.auth = $resource(_apiUri + '/auth', {}, {
|
||||||
|
@ -24,7 +24,7 @@ angular
|
|||||||
folderId: encryptedSite.FolderId,
|
folderId: encryptedSite.FolderId,
|
||||||
name: cryptoService.decrypt(encryptedSite.Name),
|
name: cryptoService.decrypt(encryptedSite.Name),
|
||||||
uri: cryptoService.decrypt(encryptedSite.Uri),
|
uri: cryptoService.decrypt(encryptedSite.Uri),
|
||||||
username: cryptoService.decrypt(encryptedSite.Username),
|
username: encryptedSite.Username && encryptedSite.Username !== '' ? cryptoService.decrypt(encryptedSite.Username) : null,
|
||||||
password: cryptoService.decrypt(encryptedSite.Password),
|
password: cryptoService.decrypt(encryptedSite.Password),
|
||||||
notes: encryptedSite.Notes && encryptedSite.Notes !== '' ? cryptoService.decrypt(encryptedSite.Notes) : null
|
notes: encryptedSite.Notes && encryptedSite.Notes !== '' ? cryptoService.decrypt(encryptedSite.Notes) : null
|
||||||
};
|
};
|
||||||
@ -79,7 +79,7 @@ angular
|
|||||||
folderId: unencryptedSite.folderId === '' ? null : unencryptedSite.folderId,
|
folderId: unencryptedSite.folderId === '' ? null : unencryptedSite.folderId,
|
||||||
uri: cryptoService.encrypt(unencryptedSite.uri, key),
|
uri: cryptoService.encrypt(unencryptedSite.uri, key),
|
||||||
name: cryptoService.encrypt(unencryptedSite.name, key),
|
name: cryptoService.encrypt(unencryptedSite.name, key),
|
||||||
username: cryptoService.encrypt(unencryptedSite.username, key),
|
username: !unencryptedSite.username || unencryptedSite.username === '' ? null : cryptoService.encrypt(unencryptedSite.username, key),
|
||||||
password: cryptoService.encrypt(unencryptedSite.password, key),
|
password: cryptoService.encrypt(unencryptedSite.password, key),
|
||||||
notes: !unencryptedSite.notes || unencryptedSite.notes === '' ? null : cryptoService.encrypt(unencryptedSite.notes, key)
|
notes: !unencryptedSite.notes || unencryptedSite.notes === '' ? null : cryptoService.encrypt(unencryptedSite.notes, key)
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,18 @@
|
|||||||
form.$errors = [];
|
form.$errors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pushError = true;
|
||||||
|
for (var i = 0; i < form.$errors.length; i++) {
|
||||||
|
if (form.$errors[i] == errorMessage) {
|
||||||
|
pushError = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pushError) {
|
||||||
form.$errors.push(errorMessage);
|
form.$errors.push(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
if (key && key !== '' && form[key] && form[key].$registerApiError) {
|
if (key && key !== '' && form[key] && form[key].$registerApiError) {
|
||||||
form[key].$registerApiError();
|
form[key].$registerApiError();
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
authService.logOut();
|
authService.logOut();
|
||||||
$state.go('frontend.login.info').then(function () {
|
$state.go('frontend.login.info').then(function () {
|
||||||
toastr.success('Please log back in.', 'Email Changed')
|
toastr.success('Please log back in.', 'Email Changed');
|
||||||
});
|
});
|
||||||
}, function () {
|
}, function () {
|
||||||
// TODO: recovery mode
|
// TODO: recovery mode
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
authService.logOut();
|
authService.logOut();
|
||||||
$state.go('frontend.login.info').then(function () {
|
$state.go('frontend.login.info').then(function () {
|
||||||
toastr.success('Please log back in.', 'Master Password Changed')
|
toastr.success('Please log back in.', 'Master Password Changed');
|
||||||
});
|
});
|
||||||
}, function () {
|
}, function () {
|
||||||
// TODO: recovery mode
|
// TODO: recovery mode
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
authService.logOut();
|
authService.logOut();
|
||||||
$state.go('frontend.login.info').then(function () {
|
$state.go('frontend.login.info').then(function () {
|
||||||
toastr.success('Please log back in.', 'All Sessions Deauthorized')
|
toastr.success('Please log back in.', 'All Sessions Deauthorized');
|
||||||
});
|
});
|
||||||
}).$promise;
|
}).$promise;
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
$scope.account = _profile.email;
|
$scope.account = _profile.email;
|
||||||
$scope.enabled = function () {
|
$scope.enabled = function () {
|
||||||
return _profile.extended && _profile.extended.twoFactorEnabled;
|
return _profile.extended && _profile.extended.twoFactorEnabled;
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.auth = function (model) {
|
$scope.auth = function (model) {
|
||||||
_masterPasswordHash = cryptoService.hashPassword(model.masterPassword);
|
_masterPasswordHash = cryptoService.hashPassword(model.masterPassword);
|
||||||
|
@ -1,7 +1,97 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.tools')
|
.module('bit.tools')
|
||||||
|
|
||||||
.controller('toolsImportController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, $q, toastr) {
|
.controller('toolsImportController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, toastr) {
|
||||||
|
$scope.model = { source: 'local' };
|
||||||
|
|
||||||
|
$scope.import = function (model) {
|
||||||
|
var file = document.getElementById('file').files[0];
|
||||||
|
|
||||||
|
// local
|
||||||
|
if (model.source == 'local') {
|
||||||
|
Papa.parse(file, {
|
||||||
|
header: true,
|
||||||
|
complete: function (results) {
|
||||||
|
console.log(results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} // lastpass
|
||||||
|
else if (model.source == 'lastpass') {
|
||||||
|
Papa.parse(file, {
|
||||||
|
header: true,
|
||||||
|
complete: function (results) {
|
||||||
|
var folders = [],
|
||||||
|
sites = [],
|
||||||
|
siteRelationships = [];
|
||||||
|
|
||||||
|
angular.forEach(results.data, function (value, key) {
|
||||||
|
if (!value.url || value.url === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var folderIndex = folders.length,
|
||||||
|
siteIndex = sites.length,
|
||||||
|
hasFolder = value.grouping && value.grouping !== '' && value.grouping != '(none)',
|
||||||
|
addFolder = hasFolder;
|
||||||
|
|
||||||
|
if (hasFolder) {
|
||||||
|
for (var i = 0; i < folders.length; i++) {
|
||||||
|
if (folders[i].name == value.grouping) {
|
||||||
|
addFolder = false;
|
||||||
|
folderIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sites.push({
|
||||||
|
uri: value.url,
|
||||||
|
username: value.username && value.username !== '' ? value.username : null,
|
||||||
|
password: value.password,
|
||||||
|
notes: value.extra && value.extra !== '' ? value.extra : null,
|
||||||
|
name: value.name
|
||||||
|
});
|
||||||
|
|
||||||
|
if (addFolder) {
|
||||||
|
folders.push({
|
||||||
|
name: value.grouping
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFolder) {
|
||||||
|
var relationship = {
|
||||||
|
key: siteIndex,
|
||||||
|
value: folderIndex
|
||||||
|
};
|
||||||
|
siteRelationships.push(relationship);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
doImport(folders, sites, siteRelationships);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// source not supported
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function doImport(folders, sites, siteRelationships) {
|
||||||
|
$scope.importPromise = apiService.tools.import({
|
||||||
|
folders: cipherService.encryptFolders(folders, cryptoService.getKey()),
|
||||||
|
sites: cipherService.encryptSites(sites, cryptoService.getKey()),
|
||||||
|
siteRelationships: siteRelationships
|
||||||
|
}, function () {
|
||||||
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
$state.go('backend.vault').then(function () {
|
||||||
|
toastr.success('Data has been successfully imported into your vault.', 'Import Success');
|
||||||
|
});
|
||||||
|
}, function () {
|
||||||
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
toastr.error('Something went wrong.', 'Oh No!');
|
||||||
|
}).$promise;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.close = function () {
|
$scope.close = function () {
|
||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,17 @@
|
|||||||
<li ng-repeat="e in importForm.$errors">{{e}}</li>
|
<li ng-repeat="e in importForm.$errors">{{e}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
Coming soon...
|
<div class="form-group" show-errors>
|
||||||
|
<label for="source">Source</label>
|
||||||
|
<select id="source" name="source" ng-model="model.source" class="form-control">
|
||||||
|
<option value="local">bitwarden</option>
|
||||||
|
<option value="lastpass">LastPass</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="file">File</label>
|
||||||
|
<input type="file" id="file" name="file" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="importForm.$loading">
|
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="importForm.$loading">
|
||||||
|
@ -14,10 +14,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
try { decSite.name = cryptoService.decrypt(sites.Data[i].Name); }
|
try { decSite.name = cryptoService.decrypt(sites.Data[i].Name); }
|
||||||
catch (err) { decSite.name = "[error: cannot decrypt]"; }
|
catch (err) { decSite.name = '[error: cannot decrypt]'; }
|
||||||
|
|
||||||
|
if (sites.Data[i].Username) {
|
||||||
try { decSite.username = cryptoService.decrypt(sites.Data[i].Username); }
|
try { decSite.username = cryptoService.decrypt(sites.Data[i].Username); }
|
||||||
catch (err) { decSite.username = "[error: cannot decrypt]"; }
|
catch (err) { decSite.username = '[error: cannot decrypt]'; }
|
||||||
|
}
|
||||||
|
|
||||||
decSites.push(decSite);
|
decSites.push(decSite);
|
||||||
}
|
}
|
||||||
@ -37,7 +39,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
try { decFolder.name = cryptoService.decrypt(folders.Data[i].Name); }
|
try { decFolder.name = cryptoService.decrypt(folders.Data[i].Name); }
|
||||||
catch (err) { decFolder.name = "[error: cannot decrypt]"; }
|
catch (err) { decFolder.name = '[error: cannot decrypt]'; }
|
||||||
|
|
||||||
decFolders.push(decFolder);
|
decFolders.push(decFolder);
|
||||||
}
|
}
|
||||||
@ -87,7 +89,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.deleteSite = function (site) {
|
$scope.deleteSite = function (site) {
|
||||||
if (!confirm("Are you sure you want to delete this site (" + site.name + ")?")) {
|
if (!confirm('Are you sure you want to delete this site (' + site.name + ')?')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +136,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.deleteFolder = function (folder) {
|
$scope.deleteFolder = function (folder) {
|
||||||
if (!confirm("Are you sure you want to delete this folder (" + folder.name + ")?")) {
|
if (!confirm('Are you sure you want to delete this folder (' + folder.name + ')?')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<div class="form-group" show-errors>
|
<div class="form-group" show-errors>
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="username" name="Username" ng-model="site.username" class="form-control" required api-field />
|
<input type="text" id="username" name="Username" ng-model="site.username" class="form-control" api-field />
|
||||||
<span class="input-group-btn" uib-tooltip="Copy Username" tooltip-placement="left">
|
<span class="input-group-btn" uib-tooltip="Copy Username" tooltip-placement="left">
|
||||||
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
|
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
|
||||||
ngclipboard-error="clipboardError(e)"
|
ngclipboard-error="clipboardError(e)"
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<div class="form-group" show-errors>
|
<div class="form-group" show-errors>
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="username" name="Username" ng-model="site.username" class="form-control" required api-field />
|
<input type="text" id="username" name="Username" ng-model="site.username" class="form-control" api-field />
|
||||||
<span class="input-group-btn" uib-tooltip="Copy Username" tooltip-placement="left">
|
<span class="input-group-btn" uib-tooltip="Copy Username" tooltip-placement="left">
|
||||||
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
|
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
|
||||||
ngclipboard-error="clipboardError(e)"
|
ngclipboard-error="clipboardError(e)"
|
||||||
|
Loading…
Reference in New Issue
Block a user