diff --git a/appinfo/routes.php b/appinfo/routes.php
index 782d0e03..0922549e 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -62,6 +62,7 @@ return [
['name' => 'share#unshareCredential', 'url' => '/api/v2/sharing/credential/{item_guid}', 'verb' => 'DELETE'],
['name' => 'share#getRevisions', 'url' => '/api/v2/sharing/credential/{item_guid}/revisions', 'verb' => 'GET'],
['name' => 'share#getItemAcl', 'url' => '/api/v2/sharing/credential/{item_guid}/acl', 'verb' => 'GET'],
+ ['name' => 'share#getFile', 'url' => '/api/v2/sharing/credential/{item_guid}/file/{file_guid}', 'verb' => 'GET'],
['name' => 'share#updateSharedCredentialACL', 'url' => '/api/v2/sharing/credential/{item_guid}/acl', 'verb' => 'PATCH'],
//Internal API
diff --git a/controller/filecontroller.php b/controller/filecontroller.php
index dc9f6a07..eef277ce 100644
--- a/controller/filecontroller.php
+++ b/controller/filecontroller.php
@@ -56,20 +56,20 @@ class FileController extends ApiController {
return $this->fileService->deleteFile($file_id, $this->userId);
}
- public function updateFile($file_id, $data, $filename, $mimetype, $size){
+ public function updateFile($file_id, $file_data, $filename, $mimetype, $size){
try{
$file = $this->fileService->getFile($file_id, $this->userId);
} catch (DoesNotExistException $doesNotExistException){
}
if($file){
- if($data) {
- $file->setFileData($data);
+ if($file_data) {
+ $file->setFileData($file_data);
}
if($filename) {
$file->setFilename($filename);
}
- if($filename || $data){
+ if($filename || $file_data){
$this->fileService->updateFile($file);
}
}
diff --git a/controller/sharecontroller.php b/controller/sharecontroller.php
index 839bffc8..b5123109 100644
--- a/controller/sharecontroller.php
+++ b/controller/sharecontroller.php
@@ -16,6 +16,7 @@ use OCA\Passman\Db\ShareRequest;
use OCA\Passman\Db\SharingACL;
use OCA\Passman\Db\Vault;
use OCA\Passman\Service\CredentialService;
+use OCA\Passman\Service\FileService;
use OCA\Passman\Service\NotificationService;
use OCA\Passman\Service\ShareService;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -23,6 +24,8 @@ use OCP\AppFramework\Http\NotFoundResponse;
use OCP\IRequest;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\ApiController;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
use OCP\IGroup;
use OCP\IGroupManager;
@@ -43,6 +46,7 @@ class ShareController extends ApiController {
private $shareService;
private $credentialService;
private $notificationService;
+ private $fileService;
private $limit = 50;
private $offset = 0;
@@ -56,7 +60,8 @@ class ShareController extends ApiController {
VaultService $vaultService,
ShareService $shareService,
CredentialService $credentialService,
- NotificationService $notificationService
+ NotificationService $notificationService,
+ FileService $fileService
) {
parent::__construct($AppName, $request);
@@ -68,6 +73,7 @@ class ShareController extends ApiController {
$this->shareService = $shareService;
$this->credentialService = $credentialService;
$this->notificationService = $notificationService;
+ $this->fileService = $fileService;
}
/**
@@ -385,6 +391,11 @@ class ShareController extends ApiController {
}
}
+ /**
+ * @param $item_guid
+ * @return JSONResponse
+ * @NoAdminRequired
+ */
public function getItemAcl($item_guid) {
$acl = $this->shareService->getCredentialAclList($item_guid);
$pending = $this->shareService->getCredentialPendingAclList($item_guid);
@@ -404,6 +415,33 @@ class ShareController extends ApiController {
}
}
+ /**
+ * @param $credential_guid
+ * @param $file_guid
+ * @NoAdminRequired
+ */
+ public function getFile($item_guid, $file_guid){
+ try {
+ $credential = $this->credentialService->getCredentialByGUID($item_guid);
+ } catch (DoesNotExistException $e){
+ return new JSONResponse(array());
+ }
+
+ $acl = $this->shareService->getACL($this->userId->getUID(), $credential->getGuid());
+ if (!$acl->hasPermission(SharingACL::FILES)){
+ return new NotFoundResponse();
+ } else {
+ return $this->fileService->getFileByGuid($file_guid);
+ }
+ }
+
+ /**
+ * @param $item_guid
+ * @param $user_id
+ * @param $permission
+ * @return JSONResponse
+ * @NoAdminRequired
+ */
public function updateSharedCredentialACL($item_guid, $user_id, $permission) {
try {
$credential = $this->credentialService->getCredentialByGUID($item_guid);
diff --git a/js/app/controllers/credential.js b/js/app/controllers/credential.js
index 514d2494..4b9eb156 100644
--- a/js/app/controllers/credential.js
+++ b/js/app/controllers/credential.js
@@ -316,17 +316,43 @@ angular.module('passmanApp')
});
- $scope.downloadFile = function (file) {
- FileService.getFile(file).then(function (result) {
- var file_data = EncryptService.decryptString(result.file_data);
+ $scope.downloadFile = function (credential, file) {
+ console.log(credential, file);
+ var callback = function(result){
+ var key = null;
+ if(!result.hasOwnProperty('file_data')){
+ NotificationService.showNotification('Error downloading file, you probably don\'t have enough permissions', 5000);
+ return;
+
+ }
+ if(!credential.hasOwnProperty('acl') && credential.hasOwnProperty('shared_key')){
+ key = EncryptService.decryptString(angular.copy(credential.shared_key));
+ }
+ if(credential.hasOwnProperty('acl')){
+ key = EncryptService.decryptString(angular.copy(credential.acl.shared_key));
+ }
+
+ var file_data = EncryptService.decryptString(result.file_data, key);
var uriContent = FileService.dataURItoBlob(file_data, file.mimetype), a = document.createElement("a");
a.style = "display: none";
+ a.id= 'downloadLink';
a.href = uriContent;
a.download = escapeHTML(file.filename);
- document.body.appendChild(a);
+ jQuery('.detailsView').append(a);
a.click();
window.URL.revokeObjectURL(uriContent);
- });
+ jQuery('#downloadLink').remove();
+ setTimeout(function(){
+ $scope.selectedCredential = credential;
+ }, 200)
+ };
+
+ if(!credential.hasOwnProperty('acl')){
+ FileService.getFile(file).then(callback);
+ } else {
+ ShareService.downloadSharedFile(credential, file).then(callback);
+ }
+
};
}]);
diff --git a/js/app/controllers/share.js b/js/app/controllers/share.js
index 8257c088..3515ac57 100644
--- a/js/app/controllers/share.js
+++ b/js/app/controllers/share.js
@@ -10,7 +10,7 @@
*/
angular.module('passmanApp')
.controller('ShareCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'ShareService', 'NotificationService', 'SharingACL','EncryptService', 'FileService',
- function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, ShareService, NotificationService, SharingACL, EncryptService) {
+ function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, ShareService, NotificationService, SharingACL, EncryptService, FileService) {
$scope.active_vault = VaultService.getActiveVault();
$scope.tabs = [{
@@ -183,7 +183,18 @@ angular.module('passmanApp')
_credential.shared_key = null;
CredentialService.updateCredential(_credential).then(function () {
NotificationService.showNotification('Credential unshared', 4000)
- })
+ });
+
+ for(var f = 0; f < $scope.storedCredential.files.length; f++){
+ var _file = $scope.storedCredential.files[f];
+ FileService.getFile(_file).then(function (fileData) {
+ console.log(fileData);
+ //Decrypt with old key
+ fileData.filename = EncryptService.decryptString(fileData.filename);
+ fileData.file_data = EncryptService.decryptString(fileData.file_data);
+ FileService.updateFile(fileData, $scope.active_vault.vaultKey);
+ })
+ }
};
/**
@@ -251,7 +262,6 @@ angular.module('passmanApp')
for (var i = 0; i < list.length; i++) {
var iterator = i;
var target_user = list[i];
- console.log(target_user)
if(target_user.hasOwnProperty('created')){
console.log('Updating permissions')
@@ -273,7 +283,6 @@ angular.module('passmanApp')
CredentialService.updateCredential(encryptedSharedCredential, true).then(function(sharedCredential){
$scope.storedCredential = ShareService.decryptSharedCredential(sharedCredential, key);
});
- console.log($scope.storedCredential);
//@TODO Update files with new key (async)
// Files are stored in $scope.storedCredential.files
@@ -281,6 +290,17 @@ angular.module('passmanApp')
// Then decrypt the data obtained with var EncryptService.decryptString(result.file_data);
// To update a file you can use the FileService.updateFile
+ for(var f = 0; f < $scope.storedCredential.files.length; f++){
+ var _file = $scope.storedCredential.files[f];
+ FileService.getFile(_file).then(function (fileData) {
+ //Decrypt with old key
+ fileData.filename = EncryptService.decryptString(fileData.filename);
+ fileData.file_data = EncryptService.decryptString(fileData.file_data);
+ FileService.updateFile(fileData, key);
+ })
+ }
+
+
//@TODO Update revisions with new key (async)
// With CredentialService.getRevisions we can get the revisions.
// Then we can update them using CredentialService.updateRevision
diff --git a/js/app/services/fileservice.js b/js/app/services/fileservice.js
index 022051c3..8e958bdf 100644
--- a/js/app/services/fileservice.js
+++ b/js/app/services/fileservice.js
@@ -60,8 +60,8 @@ angular.module('passmanApp')
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/'+ file.file_id);
var _file = angular.copy(file);
_file.filename = EncryptService.encryptString(_file.filename, key);
- var data = EncryptService.encryptString(angular.copy(file.data), key);
- _file.data = data;
+ var data = EncryptService.encryptString(angular.copy(file.file_data), key);
+ _file.file_data = data;
return $http.patch(queryUrl, _file).then(function (response) {
if (response.data) {
return response.data;
diff --git a/js/app/services/shareservice.js b/js/app/services/shareservice.js
index fb066678..d3bc68a0 100644
--- a/js/app/services/shareservice.js
+++ b/js/app/services/shareservice.js
@@ -129,6 +129,14 @@ angular.module('passmanApp')
}
});
},
+ downloadSharedFile: function (credential, file) {
+ var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/'+ credential.guid +'/file/'+ file.guid);
+ return $http.get(queryUrl).then(function (response) {
+ if (response.data) {
+ return response.data;
+ }
+ });
+ },
encryptSharedCredential: function (credential, sharedKey) {
var _credential = angular.copy(credential);
_credential.shared_key = EncryptService.encryptString(sharedKey);
diff --git a/js/templates.js b/js/templates.js
index 1e62c13f..1eb56672 100644
--- a/js/templates.js
+++ b/js/templates.js
@@ -113,7 +113,7 @@ angular.module('views/share_credential.html', []).run(['$templateCache', functio
angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('views/show_vault.html',
- '
{{filtered_credentials}} {{ ::credential.label}} {{ ::tag.text}} |
');
+ '{{filtered_credentials}} {{ ::credential.label}} {{ ::tag.text}} |
');
}]);
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 76cf20b6..d2468d79 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -20,6 +20,7 @@ use OCA\Passman\Service\ActivityService;
use OCA\Passman\Service\CronService;
use OCA\Passman\Service\CredentialService;
use OCA\Passman\Service\ShareService;
+use OCA\Passman\Service\FileService;
use OCA\Passman\Service\VaultService;
use OCA\Passman\Utility\Utils;
use OCA\Passman\Service\NotificationService;
@@ -56,7 +57,8 @@ class Application extends App {
$c->query('VaultService'),
$c->query('ShareService'),
$c->query('CredentialService'),
- $c->query('NotificationService')
+ $c->query('NotificationService'),
+ $c->query('FileService')
);
});
@@ -91,6 +93,7 @@ class Application extends App {
$container->registerAlias('NotificationService', NotificationService::class);
$container->registerAlias('ActivityService', ActivityService::class);
$container->registerAlias('VaultService', VaultService::class);
+ $container->registerAlias('FileService', FileService::class);
$container->registerAlias('ShareService', ShareService::class);
$container->registerAlias('Utils', Utils::class);
}
diff --git a/lib/Db/FileMapper.php b/lib/Db/FileMapper.php
index f9021bd3..1a72ca37 100644
--- a/lib/Db/FileMapper.php
+++ b/lib/Db/FileMapper.php
@@ -38,7 +38,24 @@ class FileMapper extends Mapper {
$sql .= ' and `user_id` = ? ';
array_push($params, $user_id);
}
- return $this->findEntities($sql, $params);
+ return $this->findEntity($sql, $params);
+ }
+ /**
+ * @param $file_id
+ * @param null $user_id
+ * @return File
+ * @throws \OCP\AppFramework\Db\DoesNotExistException if not found
+ * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result
+ */
+ public function getFileByGuid($file_guid, $user_id = null) {
+ $sql = 'SELECT * FROM `*PREFIX*passman_files` ' .
+ 'WHERE `guid` = ?';
+ $params = [$file_guid];
+ if ($user_id !== null) {
+ $sql .= ' and `user_id` = ? ';
+ array_push($params, $user_id);
+ }
+ return $this->findEntity($sql, $params);
}
public function create($file_raw, $userId) {
diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php
index 16ea1599..cf3afacd 100644
--- a/lib/Service/FileService.php
+++ b/lib/Service/FileService.php
@@ -29,6 +29,10 @@ class FileService {
return $this->fileMapper->getFile($fileId, $userId);
}
+ public function getFileByGuid($file_guid, $userId = null) {
+ return $this->fileMapper->getFileByGuid($file_guid, $userId);
+ }
+
public function createFile($file, $userId) {
return $this->fileMapper->create($file, $userId);
}
diff --git a/templates/views/show_vault.html b/templates/views/show_vault.html
index e682bd96..fafb2495 100644
--- a/templates/views/show_vault.html
+++ b/templates/views/show_vault.html
@@ -58,7 +58,7 @@
{{filtered_credentials}}
-
+
@@ -164,7 +164,7 @@
+ class="link" ng-click="downloadFile(selectedCredential, file)">
{{file.filename}} ({{file.size | bytes}})
|
@@ -248,6 +248,7 @@
+