From 858195834d6af9d1c4a5717816a5d1a431686fdc Mon Sep 17 00:00:00 2001 From: brantje Date: Wed, 28 Dec 2016 18:54:54 +0100 Subject: [PATCH] Add settings page, non functional Implement disable context menu Implemement disable http warning Implement vault key strength setting Implement share settings Implement version check setting --- appinfo/info.xml | 6 +- appinfo/routes.php | 2 + controller/credentialcontroller.php | 66 +++++----- controller/internalcontroller.php | 33 ++++- controller/sharecontroller.php | 64 +++++---- controller/translationcontroller.php | 5 + js/app/controllers/credential.js | 13 ++ js/app/controllers/main.js | 13 +- js/app/controllers/share.js | 30 ++++- js/app/controllers/vault.js | 21 ++- js/app/services/settingsservice.js | 8 +- js/settings-admin.js | 121 ++++++++++++++++++ js/templates.js | 7 +- .../ng-password-meter/ng-password-meter.js | 2 +- lib/AppInfo/Application.php | 5 +- lib/Settings/Admin.php | 70 ++++++++++ templates/settings-admin.php | 103 +++++++++++++++ templates/views/share_credential.html | 2 +- templates/views/show_vault.html | 3 +- templates/views/vaults.html | 6 +- .../controller/InternalControllerTest.php | 3 +- 21 files changed, 506 insertions(+), 77 deletions(-) create mode 100644 js/settings-admin.js create mode 100644 lib/Settings/Admin.php create mode 100644 templates/settings-admin.php diff --git a/appinfo/info.xml b/appinfo/info.xml index 1263836d..550fbc66 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -17,7 +17,7 @@ For an demo of this app visit [https://demo.passman.cc](https://demo.passman.cc) ]]> AGPL - 2.0.0-RC2 + 2.0.0-RC3 Sander Brand Marcos Zuriaga Passman @@ -40,7 +40,9 @@ For an demo of this app visit [https://demo.passman.cc](https://demo.passman.cc) sqlite mysql - + + OCA\Passman\Settings\Admin + OCA\Passman\BackgroundJob\ExpireCredentials diff --git a/appinfo/routes.php b/appinfo/routes.php index 3af8fdf2..8a90558c 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -76,6 +76,8 @@ return [ ['name' => 'internal#read', 'url' => '/api/internal/notifications/read/{credential_id}', 'verb' => 'DELETE'], ['name' => 'internal#getAppVersion', 'url' => '/api/internal/version', 'verb' => 'GET'], ['name' => 'internal#generatePerson', 'url' => '/api/internal/generate_person', 'verb' => 'GET'], + ['name' => 'internal#save_settings', 'url' => '/api/internal/settings/{key}/{value}', 'verb' => 'POST'], + ['name' => 'internal#get_settings', 'url' => '/api/internal/settings', 'verb' => 'GET'], ] ]; \ No newline at end of file diff --git a/controller/credentialcontroller.php b/controller/credentialcontroller.php index 45a6499a..fdc391fb 100644 --- a/controller/credentialcontroller.php +++ b/controller/credentialcontroller.php @@ -17,6 +17,7 @@ use OCA\Passman\Utility\NotFoundJSONResponse; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\IConfig; use OCP\IRequest; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\ApiController; @@ -33,6 +34,7 @@ class CredentialController extends ApiController { private $activityService; private $credentialRevisionService; private $sharingService; + private $config; public function __construct($AppName, IRequest $request, @@ -40,7 +42,8 @@ class CredentialController extends ApiController { CredentialService $credentialService, ActivityService $activityService, CredentialRevisionService $credentialRevisionService, - ShareService $sharingService + ShareService $sharingService, + IConfig $config ) { parent::__construct($AppName, $request); $this->userId = $userId; @@ -48,8 +51,10 @@ class CredentialController extends ApiController { $this->activityService = $activityService; $this->credentialRevisionService = $credentialRevisionService; $this->sharingService = $sharingService; + $this->config = $config; } + /** * @NoAdminRequired * @NoCSRFRequired @@ -85,7 +90,7 @@ class CredentialController extends ApiController { ); $credential = $this->credentialService->createCredential($credential); $link = ''; // @TODO create direct link to credential - if(!$credential->getHidden()) { + if (!$credential->getHidden()) { $this->activityService->add( Activity::SUBJECT_ITEM_CREATED_SELF, array($label, $this->userId), '', array(), @@ -146,7 +151,11 @@ class CredentialController extends ApiController { } else { return new DataResponse(['msg' => 'Not authorized'], Http::STATUS_UNAUTHORIZED); } + if ($this->config->getAppValue('passman', 'user_sharing_enabled', 1) === 0 || $this->config->getAppValue('passman', 'user_sharing_enabled', 1) === '0') { + return new DataResponse(['msg' => 'Not authorized'], Http::STATUS_UNAUTHORIZED); + } } + $link = ''; // @TODO create direct link to credential if ($revision_created) { $activity = 'item_apply_revision'; @@ -154,13 +163,13 @@ class CredentialController extends ApiController { $activity . '_self', array($label, $this->userId, $revision_created), '', array(), $link, $this->userId, Activity::TYPE_ITEM_ACTION); - } else if (($storedCredential->getDeleteTime() === 0) && (int) $delete_time > 0) { + } else if (($storedCredential->getDeleteTime() === 0) && (int)$delete_time > 0) { $activity = 'item_deleted'; $this->activityService->add( $activity . '_self', array($label, $this->userId), '', array(), $link, $this->userId, Activity::TYPE_ITEM_ACTION); - } else if (($storedCredential->getDeleteTime() > 0) && (int) $delete_time === 0) { + } else if (($storedCredential->getDeleteTime() > 0) && (int)$delete_time === 0) { $activity = 'item_recovered'; $this->activityService->add( $activity . '_self', array($label, $this->userId), @@ -204,7 +213,7 @@ class CredentialController extends ApiController { foreach ($acl_list as $sharingACL) { $target_user = $sharingACL->getUserId(); - if($target_user === $this->userId){ + if ($target_user === $this->userId) { continue; } $this->activityService->add( @@ -219,15 +228,15 @@ class CredentialController extends ApiController { $link, $storedCredential->getUserId(), Activity::TYPE_ITEM_ACTION); } } - if($set_share_key === true){ + if ($set_share_key === true) { $storedCredential->setSharedKey($shared_key); $credential['shared_key'] = $shared_key; } - if($unshare_action === true){ + if ($unshare_action === true) { $storedCredential->setSharedKey(''); $credential['shared_key'] = ''; } - if(!$skip_revision) { + if (!$skip_revision) { $this->credentialRevisionService->createRevision($storedCredential, $storedCredential->getUserId(), $credential_id, $this->userId); } $credential = $this->credentialService->updateCredential($credential); @@ -259,26 +268,23 @@ class CredentialController extends ApiController { * @NoCSRFRequired */ public function getRevision($credential_guid) { - try { - $credential = $this->credentialService->getCredentialByGUID($credential_guid); - } - catch (DoesNotExistException $ex){ - return new NotFoundJSONResponse(); - } + try { + $credential = $this->credentialService->getCredentialByGUID($credential_guid); + } catch (DoesNotExistException $ex) { + return new NotFoundJSONResponse(); + } - // If the request was made by the owner of the credential - if ($this->userId === $credential->getUserId()) { - $result = $this->credentialRevisionService->getRevisions($credential->getId(), $this->userId); - } - else { - $acl = $this->sharingService->getACL($this->userId, $credential_guid); - if ($acl->hasPermission(SharingACL::HISTORY)){ - $result = $this->credentialRevisionService->getRevisions($credential->getId()); - } - else { - return new NotFoundJSONResponse(); - } - } + // If the request was made by the owner of the credential + if ($this->userId === $credential->getUserId()) { + $result = $this->credentialRevisionService->getRevisions($credential->getId(), $this->userId); + } else { + $acl = $this->sharingService->getACL($this->userId, $credential_guid); + if ($acl->hasPermission(SharingACL::HISTORY)) { + $result = $this->credentialRevisionService->getRevisions($credential->getId()); + } else { + return new NotFoundJSONResponse(); + } + } return new JSONResponse($result); } @@ -296,7 +302,7 @@ class CredentialController extends ApiController { * @NoAdminRequired * @NoCSRFRequired */ - public function updateRevision($credential_guid, $revision_id, $credential_data){ + public function updateRevision($credential_guid, $revision_id, $credential_data) { $revision = null; try { $this->credentialService->getCredentialByGUID($credential_guid, $this->userId); @@ -304,9 +310,9 @@ class CredentialController extends ApiController { return new NotFoundJSONResponse(); } - try{ + try { $revision = $this->credentialRevisionService->getRevision($revision_id); - } catch(DoesNotExistException $exception){ + } catch (DoesNotExistException $exception) { return new NotFoundJSONResponse(); } diff --git a/controller/internalcontroller.php b/controller/internalcontroller.php index 01a310a9..176c71bc 100644 --- a/controller/internalcontroller.php +++ b/controller/internalcontroller.php @@ -11,6 +11,7 @@ namespace OCA\Passman\Controller; +use OCP\IConfig; use OCP\IRequest; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\ApiController; @@ -20,14 +21,18 @@ use \OCP\App; class InternalController extends ApiController { private $userId; private $credentialService; + private $config; public function __construct($AppName, IRequest $request, $UserId, - CredentialService $credentialService) { + CredentialService $credentialService, + IConfig $config + ) { parent::__construct($AppName, $request); $this->userId = $UserId; $this->credentialService = $credentialService; + $this->config = $config; } /** @@ -80,4 +85,30 @@ class InternalController extends ApiController { return new JSONResponse($random_person); } + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function getSettings() { + $settings = array( + 'link_sharing_enabled' => $this->config->getAppValue('passman', 'link_sharing_enabled', 1), + 'user_sharing_enabled' => $this->config->getAppValue('passman', 'user_sharing_enabled', 1), + 'vault_key_strength' => $this->config->getAppValue('passman', 'vault_key_strength', 3), + 'check_version' => $this->config->getAppValue('passman', 'check_version', 1), + 'https_check' => $this->config->getAppValue('passman', 'https_check', 1), + 'disable_contextmenu' => $this->config->getAppValue('passman', 'disable_contextmenu', 1), + ); + return new JSONResponse($settings); + } + + /** + * @NoCSRFRequired + */ + public function saveSettings($key, $value) { + if (is_numeric($value)) { + $value = intval($value); + } + $this->config->setAppValue('passman', $key, $value); + } + } \ No newline at end of file diff --git a/controller/sharecontroller.php b/controller/sharecontroller.php index 361d5351..aa061432 100644 --- a/controller/sharecontroller.php +++ b/controller/sharecontroller.php @@ -11,8 +11,6 @@ namespace OCA\Passman\Controller; -use OCA\Files_External\NotFoundException; -use OCA\Passman\Db\ShareRequest; use OCA\Passman\Db\SharingACL; use OCA\Passman\Db\Vault; use OCA\Passman\Service\CredentialService; @@ -23,16 +21,13 @@ use OCA\Passman\Utility\NotFoundJSONResponse; use OCA\Passman\Utility\Utils; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http\NotFoundResponse; +use OCP\IConfig; 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; use OCP\IUserManager; -use OCP\IUser; use OCA\Passman\Service\VaultService; use OCA\Passman\Service\ActivityService; @@ -49,6 +44,7 @@ class ShareController extends ApiController { private $credentialService; private $notificationService; private $fileService; + private $config; private $limit = 50; private $offset = 0; @@ -63,7 +59,8 @@ class ShareController extends ApiController { ShareService $shareService, CredentialService $credentialService, NotificationService $notificationService, - FileService $fileService + FileService $fileService, + IConfig $config ) { parent::__construct($AppName, $request); @@ -76,6 +73,13 @@ class ShareController extends ApiController { $this->credentialService = $credentialService; $this->notificationService = $notificationService; $this->fileService = $fileService; + $this->config = $config; + } + + private function isSharingEnabled() { + if ($this->config->getAppValue('passman', 'link_sharing_enabled', 1) === 0 || $this->config->getAppValue('passman', 'link_sharing_enabled', 1) === '0') { + return new JSONResponse(array()); + } } /** @@ -87,10 +91,12 @@ class ShareController extends ApiController { * @NoCSRFRequired */ public function createPublicShare($item_id, $item_guid, $permissions, $expire_timestamp, $expire_views) { + $this->isSharingEnabled(); - try{ + + try { $credential = $this->credentialService->getCredentialByGUID($item_guid); - } catch (DoesNotExistException $exception){ + } catch (DoesNotExistException $exception) { return new NotFoundResponse(); } @@ -124,6 +130,7 @@ class ShareController extends ApiController { * @NoCSRFRequired */ public function applyIntermediateShare($item_id, $item_guid, $vaults, $permissions) { + $this->isSharingEnabled(); /** * Assemble notification */ @@ -139,14 +146,14 @@ class ShareController extends ApiController { return new JSONResponse(array('error' => 'User got already pending requests')); } } catch (DoesNotExistException $exception) { - + // no need to catch this } $acl = null; try { $acl = $this->shareService->getCredentialAclForUser($first_vault['user_id'], $item_guid); } catch (DoesNotExistException $exception) { - + // no need to catch this } if ($acl) { @@ -216,6 +223,7 @@ class ShareController extends ApiController { * @NoCSRFRequired */ public function unshareCredential($item_guid) { + $this->isSharingEnabled(); $acl_list = $this->shareService->getCredentialAclList($item_guid); $request_list = $this->shareService->getShareRequestsByGuid($item_guid); foreach ($acl_list as $ACL) { @@ -234,21 +242,21 @@ class ShareController extends ApiController { } - public function unshareCredentialFromUser($item_guid, $user_id){ + public function unshareCredentialFromUser($item_guid, $user_id) { $acl = null; $sr = null; try { $acl = $this->shareService->getCredentialAclForUser($user_id, $item_guid); - } catch (DoesNotExistException $e){ + } catch (DoesNotExistException $e) { } - try{ - $sr = array_pop($this->shareService->getPendingShareRequestsForCredential($item_guid, $user_id)); - } catch (DoesNotExistException $e){ - + try { + $sr = array_pop($this->shareService->getPendingShareRequestsForCredential($item_guid, $user_id)); + } catch (DoesNotExistException $e) { + // no need to catch this } - if($sr){ + if ($sr) { $this->shareService->cleanItemRequestsForUser($sr); $manager = \OC::$server->getNotificationManager(); $notification = $manager->createNotification(); @@ -257,7 +265,7 @@ class ShareController extends ApiController { ->setUser($user_id); $manager->markProcessed($notification); } - if($acl){ + if ($acl) { $this->shareService->deleteShareACL($acl); } return new JSONResponse(array('result' => true)); @@ -355,7 +363,7 @@ class ShareController extends ApiController { try { return new JSONResponse($this->shareService->getItemHistory($this->userId, $item_guid)); } catch (DoesNotExistException $ex) { - return new NotFoundResponse(); + return new NotFoundJSONResponse(); } } @@ -366,6 +374,8 @@ class ShareController extends ApiController { * @NoCSRFRequired */ public function getVaultItems($vault_guid) { + $this->isSharingEnabled(); + try { return new JSONResponse($this->shareService->getSharedItems($this->userId->getUID(), $vault_guid)); } catch (DoesNotExistException $ex) { @@ -404,7 +414,7 @@ class ShareController extends ApiController { $this->shareService->cleanItemRequestsForUser($sr); return new JSONResponse(array('result' => true)); } catch (DoesNotExistException $ex) { - return new NotFoundResponse(); + return new NotFoundJSONResponse(); } } @@ -416,15 +426,15 @@ class ShareController extends ApiController { * @PublicPage */ public function getPublicCredentialData($credential_guid) { - + $this->isSharingEnabled(); //@TODO Check expire date $acl = $this->shareService->getACL(null, $credential_guid); - if ($acl->getExpire() > 0 && Utils::getTime() > $acl->getExpire()) { + if ($acl->getExpire() > 0 && Utils::getTime() > $acl->getExpire()) { return new NotFoundJSONResponse(); } - $views = $acl->getExpireViews(); + $views = $acl->getExpireViews(); if ($views === 0) { return new NotFoundJSONResponse(); } else if ($views !== -1) { @@ -475,15 +485,15 @@ class ShareController extends ApiController { * @return JSONResponse * @return NotFoundResponse */ - public function getFile($item_guid, $file_guid){ + public function getFile($item_guid, $file_guid) { try { $credential = $this->credentialService->getCredentialByGUID($item_guid); - } catch (DoesNotExistException $e){ + } catch (DoesNotExistException $e) { return new NotFoundJSONResponse(); } $userId = ($this->userId) ? $this->userId->getUID() : null; $acl = $this->shareService->getACL($userId, $credential->getGuid()); - if (!$acl->hasPermission(SharingACL::FILES)){ + if (!$acl->hasPermission(SharingACL::FILES)) { return new NotFoundJSONResponse(); } else { return $this->fileService->getFileByGuid($file_guid); diff --git a/controller/translationcontroller.php b/controller/translationcontroller.php index 1bf3e06c..f5fabbaa 100644 --- a/controller/translationcontroller.php +++ b/controller/translationcontroller.php @@ -96,6 +96,11 @@ class TranslationController extends ApiController { 'credential.shared' => $this->trans->t('Credential shared'), 'saved' => $this->trans->t('Saved!'), + // js/app/controllers/vault.js + 'password.poor' => $this->trans->t('Poor'), + 'password.weak' => $this->trans->t('Weak'), + 'password.good' => $this->trans->t('Good'), + 'password.strong' => $this->trans->t('Strong'), // js/app/directives/credentialfield.js 'toggle.visibility' => $this->trans->t('Toggle visibility'), 'copy.field' => $this->trans->t('Copy to clipboard'), diff --git a/js/app/controllers/credential.js b/js/app/controllers/credential.js index 2395a88a..ff1650b5 100644 --- a/js/app/controllers/credential.js +++ b/js/app/controllers/credential.js @@ -194,6 +194,19 @@ }; + var settingsLoaded = function () { + $scope.settings = SettingsService.getSettings(); + }; + + if(!SettingsService.getSetting('user_sharing_enabled')){ + $rootScope.$on('settings_loaded', function () { + settingsLoaded(); + }); + } else { + settingsLoaded(); + } + + $scope.addCredential = function () { var new_credential = CredentialService.newCredential(); var enc_c = CredentialService.encryptCredential(new_credential); diff --git a/js/app/controllers/main.js b/js/app/controllers/main.js index ffbeccec..78d97bb2 100644 --- a/js/app/controllers/main.js +++ b/js/app/controllers/main.js @@ -31,7 +31,7 @@ * Controller of the passmanApp */ angular.module('passmanApp') - .controller('MainCtrl', ['$scope', '$rootScope', '$location', function ($scope, $rootScope, $location) { + .controller('MainCtrl', ['$scope', '$rootScope', '$location', 'SettingsService', function ($scope, $rootScope, $location, SettingsService) { $scope.selectedVault = false; $scope.http_warning_hidden = true; @@ -41,6 +41,17 @@ } + $rootScope.$on('settings_loaded', function(){ + if (SettingsService.getSetting('disable_contextmenu') === '1' || SettingsService.getSetting('disable_contextmenu') === 1) { + document.addEventListener('contextmenu', function (event) { + event.preventDefault(); + }); + } + if (SettingsService.getSetting('https_check') === '0' || SettingsService.getSetting('https_check') === 0) { + $scope.http_warning_hidden = true; + } + }); + $rootScope.setHttpWarning = function (state) { $scope.http_warning_hidden = state; }; diff --git a/js/app/controllers/share.js b/js/app/controllers/share.js index 52178a12..3ac6b0e6 100644 --- a/js/app/controllers/share.js +++ b/js/app/controllers/share.js @@ -32,10 +32,13 @@ * This file is part of passman, licensed under AGPLv3 */ angular.module('passmanApp') - .controller('ShareCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'ShareService', 'NotificationService', 'SharingACL', 'EncryptService', '$translate', - function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, ShareService, NotificationService, SharingACL, EncryptService, $translate) { + .controller('ShareCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'ShareService', 'NotificationService', 'SharingACL', 'EncryptService', '$translate', '$rootScope', + function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, ShareService, NotificationService, SharingACL, EncryptService, $translate, $rootScope) { $scope.active_vault = VaultService.getActiveVault(); + + + $scope.tabs = [{ title: $translate.instant('share.u.g'), url: 'views/partials/forms/share_credential/basics.html' @@ -44,8 +47,31 @@ url: 'views/partials/forms/share_credential/link_sharing.html', color: 'green' }]; + $scope.currentTab = $scope.tabs[0]; + + var settingsLoaded = function () { + var settings = SettingsService.getSettings(); + if(settings.user_sharing_enabled === 0 || settings.user_sharing_enabled ==='0'){ + $scope.tabs.splice(0,1); + } + if(settings.link_sharing_enabled === 0 || settings.link_sharing_enabled ==='0'){ + $scope.tabs.splice(1,1); + } + if($scope.tabs.length > 0){ + $scope.currentTab = $scope.tabs[0]; + } + }; + + if(!SettingsService.getSetting('user_sharing_enabled')){ + $rootScope.$on('settings_loaded', function () { + settingsLoaded(); + }); + } else { + settingsLoaded(); + } + $scope.onClickTab = function (tab) { $scope.currentTab = tab; }; diff --git a/js/app/controllers/vault.js b/js/app/controllers/vault.js index 61aa47f5..99a868d4 100644 --- a/js/app/controllers/vault.js +++ b/js/app/controllers/vault.js @@ -31,7 +31,7 @@ * Controller of the passmanApp */ angular.module('passmanApp') - .controller('VaultCtrl', ['$scope', 'VaultService', 'SettingsService', 'CredentialService', '$location', 'ShareService', 'EncryptService', '$translate', function ($scope, VaultService, SettingsService, CredentialService, $location, ShareService, EncryptService, $translate) { + .controller('VaultCtrl', ['$scope', 'VaultService', 'SettingsService', 'CredentialService', '$location', 'ShareService', 'EncryptService', '$translate', '$rootScope', function ($scope, VaultService, SettingsService, CredentialService, $location, ShareService, EncryptService, $translate, $rootScope) { VaultService.getVaults().then(function (vaults) { $scope.vaults = vaults; if (SettingsService.getSetting('defaultVault') != null) { @@ -57,9 +57,26 @@ }); + var key_strengths = [ + 'password.poor', + 'password.poor', + 'password.weak', + 'password.good', + 'password.strong' + ]; + $scope.default_vault = false; $scope.remember_vault_password = false; $scope.list_selected_vault = false; + $scope.minimal_value_key_strength = 3; + + $rootScope.$on('settings_loaded', function () { + $scope.minimal_value_key_strength = SettingsService.getSetting('vault_key_strength'); + $translate(key_strengths[SettingsService.getSetting('vault_key_strength')]).then(function(translation){ + $scope.required_score = {'strength': translation}; + }); + + }); $scope.toggleDefaultVault = function () { $scope.default_vault = !$scope.default_vault; @@ -96,7 +113,7 @@ var key_size = 1024; ShareService.generateRSAKeys(key_size).progress(function (progress) { var p = progress > 0 ? 2 : 1; - var msg = $translate.instant('generating.sharing.keys'); + var msg = $translate.instant('generating.sharing.keys'); msg = msg.replace('%step', p); $scope.creating_keys = msg; $scope.$digest(); diff --git a/js/app/services/settingsservice.js b/js/app/services/settingsservice.js index aa3a05a5..16cf4d29 100644 --- a/js/app/services/settingsservice.js +++ b/js/app/services/settingsservice.js @@ -32,12 +32,18 @@ * Service in the passmanApp. */ angular.module('passmanApp') - .service('SettingsService', ['localStorageService', function (localStorageService) { + .service('SettingsService', ['localStorageService', '$http', '$rootScope', function (localStorageService, $http, $rootScope) { var settings = { defaultVault: null, defaultVaultPass: null }; + $http.get(OC.generateUrl('apps/passman/api/internal/settings')).then(function (response) { + if (response.data) { + settings = angular.merge(settings, response.data); + $rootScope.$broadcast('settings_loaded'); + } + }); var cookie = localStorageService.get('settings'); settings = angular.merge(settings, cookie); diff --git a/js/settings-admin.js b/js/settings-admin.js new file mode 100644 index 00000000..e84bd50f --- /dev/null +++ b/js/settings-admin.js @@ -0,0 +1,121 @@ +/** + * 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 . + * + */ + +$(document).ready(function () { + + var Settings = function (baseUrl) { + this._baseUrl = baseUrl; + this._settings = []; + }; + + Settings.prototype = { + load: function () { + var deferred = $.Deferred(); + var self = this; + $.ajax({ + url: this._baseUrl, + method: 'GET', + async: false + }).done(function (settings) { + self._settings = settings; + }).fail(function () { + deferred.reject(); + }); + return deferred.promise(); + }, + + setUserKey: function (key, value) { + var request = $.ajax({ + url: this._baseUrl + '/' + key + '/' + value, + method: 'POST' + }); + request.done(function () { + $('.msg-passwords').removeClass("msg_error"); + $('.msg-passwords').text(''); + }); + request.fail(function () { + $('.msg-passwords').addClass("msg_error"); + $('.msg-passwords').text(t('passwords', 'Error while saving field') + ' ' + key + '!'); + }); + }, + + setAdminKey: function (key, value) { + var request = $.ajax({ + url: this._baseUrl + '/' + key + '/' + value, + method: 'POST' + }); + request.done(function () { + $('.msg-passwords').removeClass("msg_error"); + $('.msg-passwords').text(''); + }); + request.fail(function () { + $('.msg-passwords').addClass("msg_error"); + $('.msg-passwords').text(t('passwords', 'Error while saving field') + ' ' + key + '!'); + }); + }, + getKey: function (key) { + if(this._settings.hasOwnProperty(key)){ + return this._settings[key]; + } + return false; + }, + getAll: function () { + return this._settings; + } + }; + + + var settings = new Settings(OC.generateUrl('apps/passman/api/internal/settings')); + settings.load(); + + // ADMIN SETTINGS + + // fill the boxes + $('#passman_link_sharing_enabled').prop('checked', (settings.getKey('link_sharing_enabled').toString().toLowerCase() == '1')); + $('#passman_sharing_enabled').prop('checked', (settings.getKey('user_sharing_enabled').toString().toLowerCase() == '1')); + $('#passman_check_version').prop('checked', (settings.getKey('check_version').toString().toLowerCase() == '1')); + $('#passman_https_check').prop('checked', (settings.getKey('https_check').toString().toLowerCase() == '1')); + $('#passman_disable_contextmenu').prop('checked', (settings.getKey('disable_contextmenu').toString().toLowerCase() == '1')); + $('#vault_key_strength').val(settings.getKey('vault_key_strength')); + + + $('#passman_check_version').change(function () { + settings.setAdminKey('check_version', ($(this).is(":checked")) ? 1 : 0); + }); + + $('#passman_https_check').change(function () { + settings.setAdminKey('https_check', ($(this).is(":checked")) ? 1 : 0); + }); + + $('#passman_disable_contextmenu').change(function () { + settings.setAdminKey('disable_contextmenu', ($(this).is(":checked")) ? 1 : 0); + }); + + $('#passman_sharing_enabled').change(function () { + settings.setAdminKey('user_sharing_enabled', ($(this).is(":checked")) ? 1 : 0); + }); + + $('#passman_link_sharing_enabled').change(function () { + settings.setAdminKey('link_sharing_enabled', ($(this).is(":checked")) ? 1 : 0); + }); + +}); diff --git a/js/templates.js b/js/templates.js index bae76d8c..80e7037f 100644 --- a/js/templates.js +++ b/js/templates.js @@ -107,17 +107,18 @@ angular.module('views/settings.html', []).run(['$templateCache', function($templ angular.module('views/share_credential.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/share_credential.html', - '
  • {{tab.title}}
'); + '
  • {{tab.title}}
'); }]); angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/show_vault.html', - '
{{ \'deleted.since\' | translate }}: All time {{delete_time | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
+
{{ ::tag.text}} {{ ::credential.label}}
  • {{ ::credential.label}}
    {{ ::tag.text}}

{{selectedCredential.label}}

{{ \'account\' | translate }}
{{ \'password\' | translate }}
{{\'otp\' | translate}}
{{\'email\' | translate}}
{{ \'url\' | translate}}
{{\'notes\' | translate}}
{{ \'files\' | translate}}
{{field.label}}
{{field.value.filename}} ({{field.value.size | bytes}})
{{ \'expire.time\' | translate }}
{{selectedCredential.expire_time * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{ \'changed\' | translate}}
{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{ \'created\' | translate}}
{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{tag.text}}
'); + '
{{ \'deleted.since\' | translate }}: All time {{delete_time | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
+
{{ ::tag.text}} {{ ::credential.label}}
  • {{ ::credential.label}}
    {{ ::tag.text}}

{{selectedCredential.label}}

{{ \'account\' | translate }}
{{ \'password\' | translate }}
{{\'otp\' | translate}}
{{\'email\' | translate}}
{{ \'url\' | translate}}
{{\'notes\' | translate}}
{{ \'files\' | translate}}
{{field.label}}
{{field.value.filename}} ({{field.value.size | bytes}})
{{ \'expire.time\' | translate }}
{{selectedCredential.expire_time * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{ \'changed\' | translate}}
{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{ \'created\' | translate}}
{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}
{{tag.text}}
'); }]); angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/vaults.html', - '
  • + Create a new vault
  • {{vault.name}}
    {{ \'created\' | translate}}: {{vault.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} | {{ \'last.access\' | translate}}: {{vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} {{\'never\' | translate}}
  • {{ \'no.vaults\' | translate}}
  • {{ \'go.back.vaults\' | translate }}
'); + '
  • + Create a new vault
  • {{vault.name}}
    {{ \'created\' | translate}}: {{vault.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} | {{ \'last.access\' | translate}}: {{vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} {{\'never\' | translate}}
  • {{ \'no.vaults\' | translate}}
  • {{ \'go.back.vaults\' | translate }}
'); }]); diff --git a/js/vendor/ng-password-meter/ng-password-meter.js b/js/vendor/ng-password-meter/ng-password-meter.js index 1cde291e..12e36a43 100644 --- a/js/vendor/ng-password-meter/ng-password-meter.js +++ b/js/vendor/ng-password-meter/ng-password-meter.js @@ -26,7 +26,7 @@ scope.matchBreakdown = false; scope.toggleScore = function () { scope.scoreShown = !scope.scoreShown; - } + }; jQuery('.match-sequence').hide(); scope.toggleMatchBreakdown = function () { scope.matchBreakdown = true; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index c2840294..ca9cdc3a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -36,6 +36,7 @@ use OCA\Passman\Service\FileService; use OCA\Passman\Service\VaultService; use OCA\Passman\Utility\Utils; use OCA\Passman\Service\NotificationService; +use OCP\IConfig; use OCP\IDBConnection; use OCP\AppFramework\App; @@ -70,7 +71,8 @@ class Application extends App { $c->query('ShareService'), $c->query('CredentialService'), $c->query('NotificationService'), - $c->query('FileService') + $c->query('FileService'), + $c->query('IConfig') ); }); @@ -109,6 +111,7 @@ class Application extends App { $container->registerAlias('ShareService', ShareService::class); $container->registerAlias('Utils', Utils::class); $container->registerAlias('IDBConnection', IDBConnection::class); + $container->registerAlias('IConfig', IConfig::class); } /** diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php new file mode 100644 index 00000000..90f27ab4 --- /dev/null +++ b/lib/Settings/Admin.php @@ -0,0 +1,70 @@ +. + * + */ + +namespace OCA\Passman\Settings; + + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IConfig; +use OCP\IL10N; +use OCP\Settings\ISettings; + +class Admin implements ISettings { + + private $config; + private $l; + + public function __construct( + IConfig $config, + IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + /** + * @return TemplateResponse + */ + public function getForm() { + + return new TemplateResponse('passman', 'settings-admin'); + } + + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() { + return 'additional'; + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * E.g.: 70 + */ + public function getPriority() { + return 0; + } + +} diff --git a/templates/settings-admin.php b/templates/settings-admin.php new file mode 100644 index 00000000..9a3e8c0a --- /dev/null +++ b/templates/settings-admin.php @@ -0,0 +1,103 @@ +getConfig()->getAppValue('passman', 'check_version', '1') === '1'; +$AppInstance = new App(); +$localVersion = $AppInstance->getAppInfo("passman")["version"]; +if ($checkVersion) { +// get latest master version + $doc = new DOMDocument(); + $doc->load('https://raw.githubusercontent.com/nextcloud/passman/master/appinfo/info.xml'); + $root = $doc->getElementsByTagName("info"); + $version = false; + $githubVersion = $l->t('Unable to get version info'); + foreach ($root as $element) { + $versions = $element->getElementsByTagName("version"); + $version = $versions->item(0)->nodeValue; + } + if ($version) { + $githubVersion = $version; + } +} +?> + +
+
+

t('Passman Settings')); ?>

+ t('Github version:'). ' '. $githubVersion); + print '
'; + } ?> + Local version:
+ t('A newer version of passman is available')); + } + ?> +

t('Sharing')); ?>

+

+ + +

+ +

+ /> + +

+

t('General')); ?>

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+
+
diff --git a/templates/views/share_credential.html b/templates/views/share_credential.html index 22477f53..b8840577 100644 --- a/templates/views/share_credential.html +++ b/templates/views/share_credential.html @@ -24,7 +24,7 @@ -