From 6caf31a9927fd5e335dc27dd90e573a3b285dc08 Mon Sep 17 00:00:00 2001 From: brantje Date: Wed, 14 Sep 2016 18:57:38 +0200 Subject: [PATCH] File upload / delete works --- appinfo/database.xml | 10 +-- appinfo/info.xml | 2 +- appinfo/routes.php | 4 +- controller/credentialcontroller.php | 14 ---- controller/filecontroller.php | 51 ++++++++++++++ controller/vaultcontroller.php | 1 + js/app/controllers/edit_credential.js | 19 ++++-- js/app/services/fileservice.js | 38 +++++++++++ js/templates.js | 2 +- lib/Db/Credential.php | 2 +- lib/Db/File.php | 66 +++++++++++++++++++ lib/Db/FileMapper.php | 55 ++++++++++++++++ lib/Db/Vault.php | 6 +- lib/Service/FileService.php | 40 +++++++++++ templates/main.php | 1 + .../partials/forms/edit_credential/files.html | 4 +- 16 files changed, 276 insertions(+), 39 deletions(-) create mode 100644 controller/filecontroller.php create mode 100644 js/app/services/fileservice.js create mode 100644 lib/Db/File.php create mode 100644 lib/Db/FileMapper.php create mode 100644 lib/Service/FileService.php diff --git a/appinfo/database.xml b/appinfo/database.xml index 1a3edd57..2b2d6eb0 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -262,10 +262,10 @@ 64 - item_id + mimetype text + 255 true - 64 filename @@ -294,12 +294,6 @@ id - - passman_file_item_id_index - - item_id - - passman_file_user_id_index diff --git a/appinfo/info.xml b/appinfo/info.xml index 8e5ebd2c..525f3f48 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -5,7 +5,7 @@ A password manager for Nextcloud AGPL Sander Brand - 1.0.2.2 + 1.0.2.3 Passman other https://github.com/nextcloud/passman/ diff --git a/appinfo/routes.php b/appinfo/routes.php index e5c2abd4..7bb559c2 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -39,8 +39,8 @@ return [ ['name' => 'credential#deleteRevision', 'url' => '/api/v2/credentials/{credential_id}/revision/{revision_id}', 'verb' => 'DELETE'], //File stuff - ['name' => 'credential#uploadFile', 'url' => '/api/v2/credentials/{credential_id}/file', 'verb' => 'POST'], - ['name' => 'credential#deleteFile', 'url' => '/api/v2/credentials/{credential_id}/file/{file_id}', 'verb' => 'DELETE'], + ['name' => 'file#uploadFile', 'url' => '/api/v2/file', 'verb' => 'POST'], + ['name' => 'file#deleteFile', 'url' => '/api/v2/file/{file_id}', 'verb' => 'DELETE'], ] ]; \ No newline at end of file diff --git a/controller/credentialcontroller.php b/controller/credentialcontroller.php index 37f5f74c..eb57fed8 100644 --- a/controller/credentialcontroller.php +++ b/controller/credentialcontroller.php @@ -99,18 +99,4 @@ class CredentialController extends ApiController { public function deleteRevision($credential_id) { return; } - - /** - * @NoAdminRequired - */ - public function uploadFile($credential_id) { - return; - } - - /** - * @NoAdminRequired - */ - public function deleteFile($credential_id) { - return; - } } \ No newline at end of file diff --git a/controller/filecontroller.php b/controller/filecontroller.php new file mode 100644 index 00000000..2a248ee6 --- /dev/null +++ b/controller/filecontroller.php @@ -0,0 +1,51 @@ + + * @copyright Sander Brand 2016 + */ + +namespace OCA\Passman\Controller; + +use OCP\IRequest; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\ApiController; +use OCA\Passman\Service\FileService; + +class FileController extends ApiController { + private $userId; + private $fileService; + public function __construct($AppName, + IRequest $request, + $UserId, + FileService $fileService){ + parent::__construct($AppName, $request); + $this->userId = $UserId; + $this->fileService = $fileService; + } + + + /** + * @NoAdminRequired + */ + public function uploadFile($data, $filename, $mimetype, $size) { + $file = array( + 'filename' => $filename, + 'size' => $size, + 'mimetype' => $mimetype, + 'file_data' => $data + ); + return $this->fileService->createFile($file, $this->userId); + } + + /** + * @NoAdminRequired + */ + public function deleteFile($file_id) { + return $this->fileService->deleteFile($file_id, $this->userId); + } +} \ No newline at end of file diff --git a/controller/vaultcontroller.php b/controller/vaultcontroller.php index 21c8aff6..2828ffc3 100644 --- a/controller/vaultcontroller.php +++ b/controller/vaultcontroller.php @@ -17,6 +17,7 @@ use OCP\AppFramework\ApiController; use OCA\Passman\Service\VaultService; use OCA\Passman\Service\CredentialService; + class VaultController extends ApiController { private $userId; private $vaultService; diff --git a/js/app/controllers/edit_credential.js b/js/app/controllers/edit_credential.js index c0fbdb17..767bafed 100644 --- a/js/app/controllers/edit_credential.js +++ b/js/app/controllers/edit_credential.js @@ -8,7 +8,7 @@ * Controller of the passmanApp */ angular.module('passmanApp') - .controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams) { + .controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService) { $scope.active_vault = VaultService.getActiveVault(); @@ -119,7 +119,7 @@ angular.module('passmanApp') $scope.deleteCustomField = function(field){ var idx = $scope.storedCredential.custom_fields.indexOf(field); $scope.storedCredential.custom_fields.splice(idx, 1); - } + }; $scope.new_file = { name: '', @@ -128,19 +128,24 @@ angular.module('passmanApp') $scope.deleteFile = function(file){ var idx = $scope.storedCredential.files.indexOf(file); - $scope.storedCredential.files.splice(idx, 1); + FileService.deleteFile(file).then(function () { + $scope.storedCredential.files.splice(idx, 1); + }); //@TODO Delete file }; $scope.fileLoaded = function (file) { var _file = { - created: new Date(), filename: file.name, size: file.size, - mimetype: file.type + mimetype: file.type, + data: file.data }; - //@TODO upload file.data - $scope.storedCredential.files.push(_file) + FileService.uploadFile(_file).then(function (result) { + delete result.file_data; + $scope.storedCredential.files.push(result); + }); + $scope.$apply() }; diff --git a/js/app/services/fileservice.js b/js/app/services/fileservice.js new file mode 100644 index 00000000..89bddb2a --- /dev/null +++ b/js/app/services/fileservice.js @@ -0,0 +1,38 @@ +'use strict'; + +/** + * @ngdoc service + * @name passmanApp.CredentialService + * @description + * # CredentialService + * Service in the passmanApp. + */ +angular.module('passmanApp') + .service('FileService', ['$http', 'EncryptService', function ($http, EncryptService) { + return { + uploadFile: function (file) { + var queryUrl = OC.generateUrl('apps/passman/api/v2/file'); + var _file = angular.copy(file); + var data = EncryptService.encryptString(angular.copy(file.data)); + _file.data = data; + return $http.post(queryUrl, _file).then(function (response) { + if(response.data){ + return response.data; + } else { + return response; + } + }); + }, + deleteFile: function (file) { + var queryUrl = OC.generateUrl('apps/passman/api/v2/file/'+ file.file_id); + var _file = angular.copy(file); + return $http.delete(queryUrl, _file).then(function (response) { + if(response.data){ + return response.data; + } else { + return response; + } + }); + }, + } + }]); diff --git a/js/templates.js b/js/templates.js index 5aa3bb21..a0c1c49c 100644 --- a/js/templates.js +++ b/js/templates.js @@ -23,7 +23,7 @@ angular.module('views/partials/forms/edit_credential/custom_fields.html', []).ru angular.module('views/partials/forms/edit_credential/files.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/partials/forms/edit_credential/files.html', - '
FilenameUpload dateTypeActions
{{ file.filename || "empty" }}{{file.created}}{{file.mimetype}}
'); + '
FilenameUpload dateSizeActions
{{ file.filename || "empty" }}{{file.created}}{{file.size}}
'); }]); angular.module('views/partials/forms/edit_credential/otp.html', []).run(['$templateCache', function($templateCache) { diff --git a/lib/Db/Credential.php b/lib/Db/Credential.php index c590dc59..b7d6de9a 100644 --- a/lib/Db/Credential.php +++ b/lib/Db/Credential.php @@ -97,7 +97,7 @@ class Credential extends Entity implements \JsonSerializable{ /** - * Turns entitie attributes into an array + * Turns entity attributes into an array */ public function jsonSerialize() { return [ diff --git a/lib/Db/File.php b/lib/Db/File.php new file mode 100644 index 00000000..5952d5f3 --- /dev/null +++ b/lib/Db/File.php @@ -0,0 +1,66 @@ + + * @copyright Sander Brand 2016 + */ + +namespace OCA\Passman\Db; +use \OCP\AppFramework\Db\Entity; + +/** + * @method integer getId() + * @method void setId(integer $value) + * @method void setGuid(string $value) + * @method string getGuid() + * @method void setUserId(string $value) + * @method string getUserid() + * @method void setMimetype(string $value) + * @method string getMimetype() + * @method void setFilename(string $value) + * @method string getFilename() + * @method void setSize(integer $value) + * @method integer getSize() + * @method void setCreated(integer $value) + * @method integer getCreated() + * @method void setFileData(string $value) + * @method string getFileData() + */ + + +class File extends Entity implements \JsonSerializable{ + + use EntityJSONSerializer; + + protected $guid; + protected $userId; + protected $mimetype; + protected $filename; + protected $size; + protected $created; + protected $fileData; + + public function __construct() { + // add types in constructor + $this->addType('created', 'integer'); + $this->addType('size', 'integer'); + } + /** + * Turns entity attributes into an array + */ + public function jsonSerialize() { + return [ + 'file_id' => $this->getId(), + 'filename' => $this->getFilename(), + 'guid' => $this->getGuid(), + 'size' => $this->getSize(), + 'file_data' => $this->getFileData(), + 'created' => $this->getCreated(), + 'mimetype' => $this->getMimetype(), + ]; + } +} \ No newline at end of file diff --git a/lib/Db/FileMapper.php b/lib/Db/FileMapper.php new file mode 100644 index 00000000..18e2c1a4 --- /dev/null +++ b/lib/Db/FileMapper.php @@ -0,0 +1,55 @@ + + * @copyright Sander Brand 2016 + */ +namespace OCA\Passman\Db; + +use OCA\Passman\Utility\Utils; +use OCP\IDBConnection; +use OCP\AppFramework\Db\Mapper; + +class FileMapper extends Mapper { + private $utils; + public function __construct(IDBConnection $db, Utils $utils) { + parent::__construct($db, 'passman_files'); + $this->utils = $utils; + } + + + /** + * @throws \OCP\AppFramework\Db\DoesNotExistException if not found + * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result + */ + public function getFile($itemId, $fileId) { + $sql = 'SELECT * FROM `*PREFIX*passman_files` ' . + 'WHERE `id` = ? and `item_id` = ? '; + return $this->findEntities($sql, [$fileId, $itemId]); + } + + public function create($file_raw, $userId){ + $file = new File(); + $file->setGuid($this->utils->GUID()); + $file->setUserId($userId); + $file->setFilename($file_raw['filename']); + $file->setSize($file_raw['size']); + $file->setCreated($this->utils->getTime()); + $file->setFileData($file_raw['file_data']); + $file->setMimetype($file_raw['mimetype']); + + + return $this->insert($file); + } + + public function deleteFile($file_id, $userId) { + $file = new File(); + $file->setId($file_id); + $file->setUserId($userId); + $this->delete($file); // TODO: Change the autogenerated stub + } +} \ No newline at end of file diff --git a/lib/Db/Vault.php b/lib/Db/Vault.php index 5da6e6f4..0d2c705d 100644 --- a/lib/Db/Vault.php +++ b/lib/Db/Vault.php @@ -23,8 +23,8 @@ use \OCP\AppFramework\Db\Entity; * @method string getUserid() * @method void setCreated(integer $value) * @method integer getCreated() - * @method void setlastAccess(integer $value) - * @method integer getlastAccess() + * @method void setLastAccess(integer $value) + * @method integer getLastAccess() */ @@ -44,7 +44,7 @@ class Vault extends Entity implements \JsonSerializable{ $this->addType('lastAccess', 'integer'); } /** - * Turns entitie attributes into an array + * Turns entity attributes into an array */ public function jsonSerialize() { return [ diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php new file mode 100644 index 00000000..cbf3e62f --- /dev/null +++ b/lib/Service/FileService.php @@ -0,0 +1,40 @@ + + * @copyright Sander Brand 2016 + */ + +namespace OCA\Passman\Service; + +use OCP\IConfig; +use OCP\AppFramework\Db\DoesNotExistException; + +use OCA\Passman\Db\FileMapper; + + +class FileService { + + private $fileMapper; + + public function __construct(FileMapper $fileMapper) { + $this->fileMapper = $fileMapper; + } + + public function getFile($userId, $fileId) { + return $this->fileMapper->getFile($userId, $fileId); + } + + public function createFile($file, $userId) { + return $this->fileMapper->create($file, $userId); + } + + public function deleteFile($file_id, $userId) { + return $this->fileMapper->deleteFile($file_id, $userId); + } + +} \ No newline at end of file diff --git a/templates/main.php b/templates/main.php index 3b8b6a86..4cf45317 100644 --- a/templates/main.php +++ b/templates/main.php @@ -34,6 +34,7 @@ script('passman', 'app/services/cacheservice'); script('passman', 'app/services/vaultservice'); script('passman', 'app/services/credentialservice'); script('passman', 'app/services/settingsservice'); +script('passman', 'app/services/fileservice'); script('passman', 'app/services/encryptservice'); script('passman', 'app/directives/passwordgen'); script('passman', 'app/directives/fileselect'); diff --git a/templates/views/partials/forms/edit_credential/files.html b/templates/views/partials/forms/edit_credential/files.html index 1f3d5a68..9070cf0d 100644 --- a/templates/views/partials/forms/edit_credential/files.html +++ b/templates/views/partials/forms/edit_credential/files.html @@ -13,7 +13,7 @@ Filename Upload date - Type + Size Actions @@ -24,7 +24,7 @@ {{file.created}} - {{file.mimetype}} + {{file.size}}