mirror of
https://github.com/nextcloud/passman.git
synced 2025-09-10 15:04:20 +08:00
Downloading shared files works
This commit is contained in:
parent
75dd4cfe34
commit
e6aef00193
12 changed files with 139 additions and 21 deletions
|
@ -62,6 +62,7 @@ return [
|
||||||
['name' => 'share#unshareCredential', 'url' => '/api/v2/sharing/credential/{item_guid}', 'verb' => 'DELETE'],
|
['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#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#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'],
|
['name' => 'share#updateSharedCredentialACL', 'url' => '/api/v2/sharing/credential/{item_guid}/acl', 'verb' => 'PATCH'],
|
||||||
|
|
||||||
//Internal API
|
//Internal API
|
||||||
|
|
|
@ -56,20 +56,20 @@ class FileController extends ApiController {
|
||||||
return $this->fileService->deleteFile($file_id, $this->userId);
|
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{
|
try{
|
||||||
$file = $this->fileService->getFile($file_id, $this->userId);
|
$file = $this->fileService->getFile($file_id, $this->userId);
|
||||||
} catch (DoesNotExistException $doesNotExistException){
|
} catch (DoesNotExistException $doesNotExistException){
|
||||||
|
|
||||||
}
|
}
|
||||||
if($file){
|
if($file){
|
||||||
if($data) {
|
if($file_data) {
|
||||||
$file->setFileData($data);
|
$file->setFileData($file_data);
|
||||||
}
|
}
|
||||||
if($filename) {
|
if($filename) {
|
||||||
$file->setFilename($filename);
|
$file->setFilename($filename);
|
||||||
}
|
}
|
||||||
if($filename || $data){
|
if($filename || $file_data){
|
||||||
$this->fileService->updateFile($file);
|
$this->fileService->updateFile($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ use OCA\Passman\Db\ShareRequest;
|
||||||
use OCA\Passman\Db\SharingACL;
|
use OCA\Passman\Db\SharingACL;
|
||||||
use OCA\Passman\Db\Vault;
|
use OCA\Passman\Db\Vault;
|
||||||
use OCA\Passman\Service\CredentialService;
|
use OCA\Passman\Service\CredentialService;
|
||||||
|
use OCA\Passman\Service\FileService;
|
||||||
use OCA\Passman\Service\NotificationService;
|
use OCA\Passman\Service\NotificationService;
|
||||||
use OCA\Passman\Service\ShareService;
|
use OCA\Passman\Service\ShareService;
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
|
@ -23,6 +24,8 @@ use OCP\AppFramework\Http\NotFoundResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
use OCP\AppFramework\ApiController;
|
use OCP\AppFramework\ApiController;
|
||||||
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
|
|
||||||
use OCP\IGroup;
|
use OCP\IGroup;
|
||||||
use OCP\IGroupManager;
|
use OCP\IGroupManager;
|
||||||
|
@ -43,6 +46,7 @@ class ShareController extends ApiController {
|
||||||
private $shareService;
|
private $shareService;
|
||||||
private $credentialService;
|
private $credentialService;
|
||||||
private $notificationService;
|
private $notificationService;
|
||||||
|
private $fileService;
|
||||||
|
|
||||||
private $limit = 50;
|
private $limit = 50;
|
||||||
private $offset = 0;
|
private $offset = 0;
|
||||||
|
@ -56,7 +60,8 @@ class ShareController extends ApiController {
|
||||||
VaultService $vaultService,
|
VaultService $vaultService,
|
||||||
ShareService $shareService,
|
ShareService $shareService,
|
||||||
CredentialService $credentialService,
|
CredentialService $credentialService,
|
||||||
NotificationService $notificationService
|
NotificationService $notificationService,
|
||||||
|
FileService $fileService
|
||||||
) {
|
) {
|
||||||
parent::__construct($AppName, $request);
|
parent::__construct($AppName, $request);
|
||||||
|
|
||||||
|
@ -68,6 +73,7 @@ class ShareController extends ApiController {
|
||||||
$this->shareService = $shareService;
|
$this->shareService = $shareService;
|
||||||
$this->credentialService = $credentialService;
|
$this->credentialService = $credentialService;
|
||||||
$this->notificationService = $notificationService;
|
$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) {
|
public function getItemAcl($item_guid) {
|
||||||
$acl = $this->shareService->getCredentialAclList($item_guid);
|
$acl = $this->shareService->getCredentialAclList($item_guid);
|
||||||
$pending = $this->shareService->getCredentialPendingAclList($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) {
|
public function updateSharedCredentialACL($item_guid, $user_id, $permission) {
|
||||||
try {
|
try {
|
||||||
$credential = $this->credentialService->getCredentialByGUID($item_guid);
|
$credential = $this->credentialService->getCredentialByGUID($item_guid);
|
||||||
|
|
|
@ -316,17 +316,43 @@ angular.module('passmanApp')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$scope.downloadFile = function (file) {
|
$scope.downloadFile = function (credential, file) {
|
||||||
FileService.getFile(file).then(function (result) {
|
console.log(credential, file);
|
||||||
var file_data = EncryptService.decryptString(result.file_data);
|
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");
|
var uriContent = FileService.dataURItoBlob(file_data, file.mimetype), a = document.createElement("a");
|
||||||
a.style = "display: none";
|
a.style = "display: none";
|
||||||
|
a.id= 'downloadLink';
|
||||||
a.href = uriContent;
|
a.href = uriContent;
|
||||||
a.download = escapeHTML(file.filename);
|
a.download = escapeHTML(file.filename);
|
||||||
document.body.appendChild(a);
|
jQuery('.detailsView').append(a);
|
||||||
a.click();
|
a.click();
|
||||||
window.URL.revokeObjectURL(uriContent);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*/
|
*/
|
||||||
angular.module('passmanApp')
|
angular.module('passmanApp')
|
||||||
.controller('ShareCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'ShareService', 'NotificationService', 'SharingACL','EncryptService', 'FileService',
|
.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.active_vault = VaultService.getActiveVault();
|
||||||
|
|
||||||
$scope.tabs = [{
|
$scope.tabs = [{
|
||||||
|
@ -183,7 +183,18 @@ angular.module('passmanApp')
|
||||||
_credential.shared_key = null;
|
_credential.shared_key = null;
|
||||||
CredentialService.updateCredential(_credential).then(function () {
|
CredentialService.updateCredential(_credential).then(function () {
|
||||||
NotificationService.showNotification('Credential unshared', 4000)
|
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++) {
|
for (var i = 0; i < list.length; i++) {
|
||||||
var iterator = i;
|
var iterator = i;
|
||||||
var target_user = list[i];
|
var target_user = list[i];
|
||||||
console.log(target_user)
|
|
||||||
if(target_user.hasOwnProperty('created')){
|
if(target_user.hasOwnProperty('created')){
|
||||||
console.log('Updating permissions')
|
console.log('Updating permissions')
|
||||||
|
|
||||||
|
@ -273,7 +283,6 @@ angular.module('passmanApp')
|
||||||
CredentialService.updateCredential(encryptedSharedCredential, true).then(function(sharedCredential){
|
CredentialService.updateCredential(encryptedSharedCredential, true).then(function(sharedCredential){
|
||||||
$scope.storedCredential = ShareService.decryptSharedCredential(sharedCredential, key);
|
$scope.storedCredential = ShareService.decryptSharedCredential(sharedCredential, key);
|
||||||
});
|
});
|
||||||
console.log($scope.storedCredential);
|
|
||||||
|
|
||||||
//@TODO Update files with new key (async)
|
//@TODO Update files with new key (async)
|
||||||
// Files are stored in $scope.storedCredential.files
|
// 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);
|
// Then decrypt the data obtained with var EncryptService.decryptString(result.file_data);
|
||||||
// To update a file you can use the FileService.updateFile
|
// 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)
|
//@TODO Update revisions with new key (async)
|
||||||
// With CredentialService.getRevisions we can get the revisions.
|
// With CredentialService.getRevisions we can get the revisions.
|
||||||
// Then we can update them using CredentialService.updateRevision
|
// Then we can update them using CredentialService.updateRevision
|
||||||
|
|
|
@ -60,8 +60,8 @@ angular.module('passmanApp')
|
||||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/'+ file.file_id);
|
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/'+ file.file_id);
|
||||||
var _file = angular.copy(file);
|
var _file = angular.copy(file);
|
||||||
_file.filename = EncryptService.encryptString(_file.filename, key);
|
_file.filename = EncryptService.encryptString(_file.filename, key);
|
||||||
var data = EncryptService.encryptString(angular.copy(file.data), key);
|
var data = EncryptService.encryptString(angular.copy(file.file_data), key);
|
||||||
_file.data = data;
|
_file.file_data = data;
|
||||||
return $http.patch(queryUrl, _file).then(function (response) {
|
return $http.patch(queryUrl, _file).then(function (response) {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
return response.data;
|
return response.data;
|
||||||
|
|
|
@ -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) {
|
encryptSharedCredential: function (credential, sharedKey) {
|
||||||
var _credential = angular.copy(credential);
|
var _credential = angular.copy(credential);
|
||||||
_credential.shared_key = EncryptService.encryptString(sharedKey);
|
_credential.shared_key = EncryptService.encryptString(sharedKey);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -20,6 +20,7 @@ use OCA\Passman\Service\ActivityService;
|
||||||
use OCA\Passman\Service\CronService;
|
use OCA\Passman\Service\CronService;
|
||||||
use OCA\Passman\Service\CredentialService;
|
use OCA\Passman\Service\CredentialService;
|
||||||
use OCA\Passman\Service\ShareService;
|
use OCA\Passman\Service\ShareService;
|
||||||
|
use OCA\Passman\Service\FileService;
|
||||||
use OCA\Passman\Service\VaultService;
|
use OCA\Passman\Service\VaultService;
|
||||||
use OCA\Passman\Utility\Utils;
|
use OCA\Passman\Utility\Utils;
|
||||||
use OCA\Passman\Service\NotificationService;
|
use OCA\Passman\Service\NotificationService;
|
||||||
|
@ -56,7 +57,8 @@ class Application extends App {
|
||||||
$c->query('VaultService'),
|
$c->query('VaultService'),
|
||||||
$c->query('ShareService'),
|
$c->query('ShareService'),
|
||||||
$c->query('CredentialService'),
|
$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('NotificationService', NotificationService::class);
|
||||||
$container->registerAlias('ActivityService', ActivityService::class);
|
$container->registerAlias('ActivityService', ActivityService::class);
|
||||||
$container->registerAlias('VaultService', VaultService::class);
|
$container->registerAlias('VaultService', VaultService::class);
|
||||||
|
$container->registerAlias('FileService', FileService::class);
|
||||||
$container->registerAlias('ShareService', ShareService::class);
|
$container->registerAlias('ShareService', ShareService::class);
|
||||||
$container->registerAlias('Utils', Utils::class);
|
$container->registerAlias('Utils', Utils::class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,24 @@ class FileMapper extends Mapper {
|
||||||
$sql .= ' and `user_id` = ? ';
|
$sql .= ' and `user_id` = ? ';
|
||||||
array_push($params, $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) {
|
public function create($file_raw, $userId) {
|
||||||
|
|
|
@ -29,6 +29,10 @@ class FileService {
|
||||||
return $this->fileMapper->getFile($fileId, $userId);
|
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) {
|
public function createFile($file, $userId) {
|
||||||
return $this->fileMapper->create($file, $userId);
|
return $this->fileMapper->create($file, $userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{filtered_credentials}}
|
{{filtered_credentials}}
|
||||||
<div off-click="closeSelected()">
|
<div off-click="closeSelected()" off-click-filter="'#downloadLink'">
|
||||||
|
|
||||||
<div class="loaderContainer" ng-if="show_spinner">
|
<div class="loaderContainer" ng-if="show_spinner">
|
||||||
<div class="loader" use-theme type="'border-bottom-color'"></div>
|
<div class="loader" use-theme type="'border-bottom-color'"></div>
|
||||||
|
@ -164,7 +164,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div ng-repeat="file in selectedCredential.files"
|
<div ng-repeat="file in selectedCredential.files"
|
||||||
class="link" ng-click="downloadFile(file)">
|
class="link" ng-click="downloadFile(selectedCredential, file)">
|
||||||
{{file.filename}} ({{file.size | bytes}})
|
{{file.filename}} ({{file.size | bytes}})
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -248,6 +248,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="share_popup" style="display: none">
|
<div class="share_popup" style="display: none">
|
||||||
|
|
Loading…
Add table
Reference in a new issue