mirror of
https://github.com/nextcloud/passman.git
synced 2025-02-28 17:35:27 +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#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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
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\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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{{filtered_credentials}}
|
||||
<div off-click="closeSelected()">
|
||||
<div off-click="closeSelected()" off-click-filter="'#downloadLink'">
|
||||
|
||||
<div class="loaderContainer" ng-if="show_spinner">
|
||||
<div class="loader" use-theme type="'border-bottom-color'"></div>
|
||||
|
@ -164,7 +164,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<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}})
|
||||
</div>
|
||||
</td>
|
||||
|
@ -248,6 +248,7 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="share_popup" style="display: none">
|
||||
|
|
Loading…
Reference in a new issue