diff --git a/Gruntfile.js b/Gruntfile.js index fe4ec67a..f394e4da 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,6 +34,7 @@ module.exports = function (grunt) { globals: { "angular": true, "PassmanImporter": true, + "PassmanExporter": true, "OC": true, "window": true, "console": true, diff --git a/js/app/controllers/export.js b/js/app/controllers/export.js index 6a849404..56f4d5b3 100644 --- a/js/app/controllers/export.js +++ b/js/app/controllers/export.js @@ -1,7 +1,6 @@ (function () { 'use strict'; - /** * @ngdoc function * @name passmanApp.controller:ImportCtrl @@ -10,7 +9,55 @@ * Controller of the passmanApp */ angular.module('passmanApp') - .controller('ExportCtrl', ['$scope', function ($scope) { + .controller('ExportCtrl', ['$scope', '$window', 'CredentialService', 'VaultService', function ($scope, $window, CredentialService, VaultService) { + $scope.available_exporters = []; + $scope.active_vault = VaultService.getActiveVault(); + + + $scope.$watch(function () { + return $window.PassmanExporter; + }, function (exporters) { + exporters = Object.keys(angular.copy(exporters)); + for (var i = 0; i < exporters.length; i++) { + var exporter = exporters[i]; + if ($window.PassmanExporter[exporter].hasOwnProperty('info')) { + $scope.available_exporters.push($window.PassmanExporter[exporter].info); + } + } + }, true); + $scope.log = []; + $scope.setExporter = function (exporter) { + exporter = JSON.parse(exporter); + $scope.selectedExporter = exporter; + }; + var _log = function (str) { + $scope.log.push(str); + }; + + + $scope.startExport = function () { + _log('Starting export'); + var _credentials = []; + VaultService.getVault(VaultService.getActiveVault()).then(function (vault) { + _log('Decrypting credentials'); + if (vault.hasOwnProperty('credentials')) { + if (vault.credentials.length > 0) { + for (var i = 0; i < vault.credentials.length; i++) { + var _credential = angular.copy(vault.credentials[i]); + if (_credential.hidden === 0) { + _credential = CredentialService.decryptCredential(_credential); + _credentials.push(_credential); + } + } + $window.PassmanExporter[$scope.selectedExporter.id].export(_credentials).then(function () { + _log('Done'); + }); + } + + } + }); + }; + }]); diff --git a/js/exporters/exporter-csv.js b/js/exporters/exporter-csv.js new file mode 100644 index 00000000..01483d4f --- /dev/null +++ b/js/exporters/exporter-csv.js @@ -0,0 +1,43 @@ +/** global: PassmanExporter */ +PassmanExporter.csv = { + info: { + name: 'CSV', + id: 'csv', + description: 'Export credentials as csv.' + } +}; + +PassmanExporter.csv.export = function (credentials) { + /** global: C_Promise */ + return new C_Promise(function () { + var _this = this; + var headers = ['label', 'username', 'password', 'email', 'description', 'tags']; + var file_data = '"' + headers.join('","') + '"\n'; + for (var i = 0; i < credentials.length; i++) { + var _credential = credentials[i]; + var row_data = []; + for (var h = 0; h < headers.length; h++) { + var field = headers[h]; + if (field === 'tags') { + var _tags = []; + for (var t = 0; t < _credential[field].length; t++) { + _tags.push(_credential[field][t].text); + } + var data = '[' + _tags.join(",") + ']'; + row_data.push('"' + data + '"'); + } else { + row_data.push('"' + _credential[field] + '"'); + } + } + var progress = { + percent: i / credentials.length * 100, + loaded: i, + total: credentials.length + }; + _this.call_progress(progress); + file_data += row_data.join(',') + "\n"; + } + _this.call_then(); + download(file_data, 'passman-export.csv'); + }); +}; diff --git a/js/exporters/exporter-main.js b/js/exporters/exporter-main.js new file mode 100644 index 00000000..0d88f926 --- /dev/null +++ b/js/exporters/exporter-main.js @@ -0,0 +1,5 @@ +// Importers should always start with this +if (!window['PassmanExporter']) { + var PassmanExporter = {} +} + diff --git a/js/templates.js b/js/templates.js index d3b2e0ac..f1920973 100644 --- a/js/templates.js +++ b/js/templates.js @@ -45,7 +45,7 @@ angular.module('views/partials/forms/edit_credential/password.html', []).run(['$ angular.module('views/partials/forms/settings/export.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/partials/forms/settings/export.html', - '
Export credentials
'); + '
{{selectedExporter.description}}
'); }]); angular.module('views/partials/forms/settings/general_settings.html', []).run(['$templateCache', function($templateCache) { diff --git a/templates/main.php b/templates/main.php index e0a2db93..2076192f 100644 --- a/templates/main.php +++ b/templates/main.php @@ -77,6 +77,8 @@ script('passman', 'importers/importer-passmanjson'); script('passman', 'importers/importer-clipperz'); script('passman', 'importers/importer-passpackcsv'); script('passman', 'importers/importer-randomdata'); +script('passman', 'exporters/exporter-main'); +script('passman', 'exporters/exporter-csv'); /* * Styles diff --git a/templates/views/partials/forms/settings/export.html b/templates/views/partials/forms/settings/export.html index 6c11a281..865bf928 100644 --- a/templates/views/partials/forms/settings/export.html +++ b/templates/views/partials/forms/settings/export.html @@ -1,3 +1,23 @@
- Export credentials +
+
+ +
{{selectedExporter.description}}
+ +
+
+
+ +
+
+
\ No newline at end of file