Added import for lastpass csv. Username no longer required.

This commit is contained in:
Kyle Spearrin 2015-12-26 23:15:35 -05:00
parent 49921f7355
commit 9aa62e748c
12 changed files with 132 additions and 22 deletions

View File

@ -21,10 +21,6 @@
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', {}, {
registerToken: { url: _apiUri + '/accounts/register-token', method: 'POST', params: {} },
register: { url: _apiUri + '/accounts/register', method: 'POST', params: {} },
@ -36,7 +32,8 @@
getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} },
putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'PUT', 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', {}, {

View File

@ -24,7 +24,7 @@ angular
folderId: encryptedSite.FolderId,
name: cryptoService.decrypt(encryptedSite.Name),
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),
notes: encryptedSite.Notes && encryptedSite.Notes !== '' ? cryptoService.decrypt(encryptedSite.Notes) : null
};
@ -79,7 +79,7 @@ angular
folderId: unencryptedSite.folderId === '' ? null : unencryptedSite.folderId,
uri: cryptoService.encrypt(unencryptedSite.uri, 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),
notes: !unencryptedSite.notes || unencryptedSite.notes === '' ? null : cryptoService.encrypt(unencryptedSite.notes, key)
};

View File

@ -41,7 +41,18 @@
form.$errors = [];
}
form.$errors.push(errorMessage);
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);
}
if (key && key !== '' && form[key] && form[key].$registerApiError) {
form[key].$registerApiError();
}

View File

@ -50,7 +50,7 @@
$uibModalInstance.dismiss('cancel');
authService.logOut();
$state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'Email Changed')
toastr.success('Please log back in.', 'Email Changed');
});
}, function () {
// TODO: recovery mode

View File

@ -37,7 +37,7 @@
$uibModalInstance.dismiss('cancel');
authService.logOut();
$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 () {
// TODO: recovery mode

View File

@ -11,7 +11,7 @@
$uibModalInstance.dismiss('cancel');
authService.logOut();
$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;
};

View File

@ -9,7 +9,7 @@
$scope.account = _profile.email;
$scope.enabled = function () {
return _profile.extended && _profile.extended.twoFactorEnabled;
}
};
$scope.auth = function (model) {
_masterPasswordHash = cryptoService.hashPassword(model.masterPassword);

View File

@ -1,7 +1,97 @@
angular
.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 () {
$uibModalInstance.dismiss('cancel');
};

View File

@ -10,7 +10,17 @@
<li ng-repeat="e in importForm.$errors">{{e}}</li>
</ul>
</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 class="modal-footer">
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="importForm.$loading">

View File

@ -14,10 +14,12 @@
};
try { decSite.name = cryptoService.decrypt(sites.Data[i].Name); }
catch (err) { decSite.name = "[error: cannot decrypt]"; }
catch (err) { decSite.name = '[error: cannot decrypt]'; }
try { decSite.username = cryptoService.decrypt(sites.Data[i].Username); }
catch (err) { decSite.username = "[error: cannot decrypt]"; }
if (sites.Data[i].Username) {
try { decSite.username = cryptoService.decrypt(sites.Data[i].Username); }
catch (err) { decSite.username = '[error: cannot decrypt]'; }
}
decSites.push(decSite);
}
@ -37,7 +39,7 @@
};
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);
}
@ -87,7 +89,7 @@
};
$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;
}
@ -134,7 +136,7 @@
};
$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;
}

View File

@ -44,7 +44,7 @@
<div class="form-group" show-errors>
<label for="username">Username</label>
<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">
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
ngclipboard-error="clipboardError(e)"

View File

@ -47,7 +47,7 @@
<div class="form-group" show-errors>
<label for="username">Username</label>
<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">
<button tabindex="-1" class="btn btn-default btn-flat" type="button" ngclipboard
ngclipboard-error="clipboardError(e)"