Merge branch 'csv_export_fix'

This commit is contained in:
brantje 2017-07-01 18:37:04 +02:00
commit 63466f8c61
No known key found for this signature in database
GPG key ID: 5FF1D117F918687F
11 changed files with 210 additions and 46 deletions

View file

@ -31,7 +31,7 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('ExportCtrl', ['$scope', '$window', 'CredentialService', 'VaultService', '$translate', function ($scope, $window, CredentialService, VaultService, $translate) {
.controller('ExportCtrl', ['$scope', '$window', 'CredentialService', 'VaultService', 'FileService', 'EncryptService', '$translate', function ($scope, $window, CredentialService, VaultService, FileService, EncryptService, $translate) {
$scope.available_exporters = [];
$scope.active_vault = VaultService.getActiveVault();
$scope.confirm_key = '';
@ -76,10 +76,11 @@
if (_credential.hidden === 0) {
var key = CredentialService.getSharedKeyFromCredential(_credential);
_credential = CredentialService.decryptCredential(_credential, key);
_credential.vault_key = key;
_credentials.push(_credential);
}
}
$window.PassmanExporter[$scope.selectedExporter.id].export(_credentials).then(function () {
$window.PassmanExporter[$scope.selectedExporter.id].export(_credentials, FileService, EncryptService).then(function () {
_log($translate.instant('done'));
});
}

View file

@ -26,41 +26,52 @@ PassmanExporter.csv = {
info: {
name: 'CSV',
id: 'csv',
description: 'Export credentials as csv.'
description: 'Export credentials as a csv file.'
}
};
PassmanExporter.csv.export = function (credentials) {
PassmanExporter.csv.export = function (credentials, FileService, EncryptService) {
/** global: C_Promise */
return new C_Promise(function () {
var _this = this;
var headers = ['label', 'username', 'password', 'email', 'description', 'tags', 'url'];
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');
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService).then((function(){
var headers = ['label', 'username', 'password', 'email', 'description', 'tags', 'url', 'custom_fields', 'files'];
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 tag_data = '[' + _tags.join(",") + ']';
row_data.push('"' + tag_data + '"');
}
else if (field == 'custom_fields' || field == 'files') {
var _fields = JSON.stringify(_credential[field]);
_fields = _fields.replaceAll('"', '""');
row_data.push('"' + _fields + '"');
}
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');
}).bind(this)).progress(function() {
});
});
};

View file

@ -0,0 +1,63 @@
/**
* Nextcloud - passman
*
* @copyright Copyright (c) 2016, Sander Brand (brantje@gmail.com)
* @copyright Copyright (c) 2016, Marcos Zuriaga Miguel (wolfi@wolfi.es)
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** global: PassmanExporter */
PassmanExporter.json = {
info: {
name: 'JSON',
id: 'json',
description: 'Export credentials as a JSON file.'
}
};
PassmanExporter.json.export = function (credentials, FileService, EncryptService) {
/** global: C_Promise */
return new C_Promise(function () {
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService).then((function(){
var _output = [];
for (var i = 0; i < credentials.length; i++) {
var _credential = angular.copy(credentials[i]);
delete _credential.vault_key;
delete _credential.vault_id;
delete _credential.shared_key;
_output.push(_credential);
var progress = {
percent: i / credentials.length * 100,
loaded: i,
total: credentials.length
};
this.call_progress(progress);
}
var file_data = JSON.stringify(_output);
this.call_then();
download(file_data, 'passman-export.json');
}).bind(this)).progress(function() {
});
});
};

View file

@ -22,6 +22,83 @@
// Importers should always start with this
if (!window['PassmanExporter']) {
var PassmanExporter = {}
}
var PassmanExporter = {
getCredentialsWithFiles: function(credentials, FileService, EncryptService) {
var t = {
cred: credentials,
FS: FileService,
ES: EncryptService
};
/** global: C_Promise */
return new C_Promise(function() {
var _this = this.parent;
var credentials = _this.cred;
this.parent.total = 0;
this.parent.finished = 0;
this.parent.fileGUID_cred = [];
this.parent.files = [];
this.parent.step = (function(file) {
this.parent.finished ++;
this.call_progress({
total: this.parent.total,
finished: this.parent.finished
});
var dta = this.parent.fileGUID_cred[file.guid];
file.filename = this.parent.ES.decryptString(file.filename, this.parent.cred[dta.cred_pos].vault_key);
file.file_data = this.parent.ES.decryptString(file.file_data, this.parent.cred[dta.cred_pos].vault_key);
// Files and custom_fields have different field structure
if (dta.on === 'files') {
this.parent.cred[dta.cred_pos][dta.on][dta.at] = file;
}
else {
this.parent.cred[dta.cred_pos][dta.on][dta.at].value = file;
}
// We have finished downloading everything, so let's hand over job to somewhere else!
if (this.parent.total === this.parent.finished) {
this.call_then(this.parent.cred);
}
}).bind(this);
for (var i = 0; i < credentials.length; i++) {
var item = credentials[i];
// Custom fields
for (c = 0; c < item.custom_fields.length; c++) {
var cf = item.custom_fields[c];
if (cf.field_type === 'file') {
this.parent.total ++;
this.parent.fileGUID_cred[cf.value.guid] = {
cred_pos: i,
on: 'custom_fields',
at: c
};
this.parent.FS.getFile(cf.value).then((function(data){
this.parent.step(data);
}).bind(this));
}
}
// Also get all files
for (var c = 0; c < item.files.length; c++) {
this.parent.total ++;
this.parent.fileGUID_cred[item.files[c].guid] = {
cred_pos: i,
on: 'files',
at: c
};
this.parent.FS.getFile(item.files[c]).then((function(data){
this.parent.step(data);
}).bind(this));
}
}
}, t);
}
};
}

4
launch_phpunit.sh → launch_phpunit.sh.sample Executable file → Normal file
View file

@ -1,7 +1,7 @@
#!/bin/bash
# Setup your testing environment paths
export SERVER_BASE_DIR=/var/www/html/nextcloud/
export SERVER_CONFIG_DIR=/var/www/html/nextcloud/config/
export SERVER_BASE_DIR=/var/www/html/
export SERVER_CONFIG_DIR=/var/www/html/config/
export SERVER_CONFIG_FILE=config.php
# Launch the actual tests

View file

@ -1,7 +1,7 @@
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="integration">
<directory>./tests/integration</directory>
<!-- <directory>./tests/integration</directory> -->
</testsuite>
</testsuites>
</phpunit>

View file

@ -13,8 +13,8 @@
<!--<file>/path/to/file</file>-->
<!--<exclude>-->
<!--<directory suffix=".php">/path/to/dir</directory>-->
<!--<file>/path/to/file</file>-->
<!--<directory suffix=".php">/path/to/dir</directory>-->
<!--<file>/path/to/file</file>-->
<!--</exclude>-->
</whitelist>

View file

@ -94,6 +94,7 @@ script('passman', 'importers/importer-passpackcsv');
script('passman', 'importers/importer-randomdata');
script('passman', 'exporters/exporter-main');
script('passman', 'exporters/exporter-csv');
script('passman', 'exporters/exporter-json');
/*build-js-end*/

View file

@ -9,9 +9,11 @@
* @copyright Sander Brand 2016
*/
require_once __DIR__ . '/../../../tests/bootstrap.php';
require_once __DIR__ . '/../appinfo/autoload.php';
#require_once __DIR__ . '/db/DatabaseHelperTest.php';
require_once __DIR__ . '/db/DatabaseHelperTest.php';
// Fix for "Autoload path not allowed: .../tests/lib/testcase.php"

View file

@ -48,16 +48,21 @@ abstract class DatabaseHelperTest extends PHPUnit_Extensions_Database_TestCase {
* @var PHPUnit_Extensions_Database_DataSet_MysqlXmlDataSet[]
*/
protected $datasets;
/**
*
* @var \OC\Server
*/
static protected $server = NULL;
public function __construct() {
parent::__construct();
}
public function setUp() {
$server = new \OC\Server(getenv('SERVER_BASE_DIR'), new \OC\Config(getenv('SERVER_CONFIG_DIR'), getenv('SERVER_CONFIG_FILE')));
$this->app_container = $server->query('passman');
if (self::$server === NULL) self::$server = new \OC\Server(getenv('SERVER_BASE_DIR'), new \OC\Config(getenv('SERVER_CONFIG_DIR'), getenv('SERVER_CONFIG_FILE')));
$this->db = $this->app_container->getServer()->getDatabaseConnection();
$this->db = self::$server->getDatabaseConnection();
$this->datasets = [];
$tables = $this->getTablesNames();

View file

@ -43,7 +43,11 @@ class ExpireCredentialsTest extends PHPUnit_Framework_TestCase {
$jobList = $this->getMockBuilder('\OCP\BackgroundJob\IJobList')->getMock();
/** @var \OC\BackgroundJob\JobList $jobList */
$backgroundJob->execute($jobList);
$this->assertTrue(true);
try {
$backgroundJob->execute($jobList);
}
catch (Exception $ex) {
$this->assertTrue(false);
}
}
}