mirror of
https://github.com/nextcloud/passman.git
synced 2025-09-06 21:14:22 +08:00
Add feature to request vault destructions
This commit is contained in:
parent
514cb569fb
commit
fd8dcc6c1c
29 changed files with 667 additions and 43 deletions
|
@ -29,6 +29,7 @@ module.exports = function (grunt) {
|
|||
},
|
||||
jshint: {
|
||||
options: {
|
||||
reporter: require('jshint-stylish'),
|
||||
curly: false,
|
||||
eqeqeq: true,
|
||||
eqnull: true,
|
||||
|
|
|
@ -548,4 +548,44 @@
|
|||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*passman_delete_vault_request</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>true</autoincrement>
|
||||
<unsigned>true</unsigned>
|
||||
<primary>true</primary>
|
||||
<length>8</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>vault_guid</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>reason</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>requested_by</name>
|
||||
<type>text</type>
|
||||
<notnull>false</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>created</name>
|
||||
<type>integer</type>
|
||||
<length>64</length>
|
||||
<default>0</default>
|
||||
<notnull>false</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
</database>
|
|
@ -18,7 +18,7 @@ For an demo of this app visit [https://demo.passman.cc](https://demo.passman.cc)
|
|||
]]></description>
|
||||
|
||||
<licence>AGPL</licence>
|
||||
<version>2.1.0</version>
|
||||
<version>2.1.1</version>
|
||||
<author homepage="https://github.com/brantje">Sander Brand</author>
|
||||
<author homepage="https://github.com/animalillo">Marcos Zuriaga</author>
|
||||
<namespace>Passman</namespace>
|
||||
|
|
|
@ -88,5 +88,9 @@ return [
|
|||
//Admin routes
|
||||
['name' => 'admin#searchUser', 'url' => '/admin/search', 'verb' => 'GET'],
|
||||
['name' => 'admin#moveCredentials', 'url' => '/admin/move', 'verb' => 'POST'],
|
||||
['name' => 'admin#requestDeletion', 'url' => '/admin/request-deletion/{vault_guid}', 'verb' => 'POST'],
|
||||
['name' => 'admin#deleteRequestDeletion', 'url' => '/admin/request-deletion/{vault_guid}', 'verb' => 'DELETE'],
|
||||
['name' => 'admin#listRequests', 'url' => '/admin/delete-requests', 'verb' => 'GET'],
|
||||
['name' => 'admin#acceptRequestDeletion', 'url' => '/admin/accept-delete-request', 'verb' => 'POST'],
|
||||
]
|
||||
];
|
|
@ -12,15 +12,19 @@
|
|||
namespace OCA\Passman\Controller;
|
||||
|
||||
use OCA\Passman\Db\CredentialRevision;
|
||||
use OCA\Passman\Db\DeleteVaultRequest;
|
||||
use OCA\Passman\Service\CredentialRevisionService;
|
||||
use OCA\Passman\Service\DeleteVaultRequestService;
|
||||
use OCA\Passman\Service\FileService;
|
||||
use OCA\Passman\Service\VaultService;
|
||||
use OCA\Passman\Utility\Utils;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCA\Passman\Service\CredentialService;
|
||||
use \OCP\App;
|
||||
use OCP\JSON;
|
||||
|
||||
class AdminController extends ApiController {
|
||||
private $userId;
|
||||
|
@ -28,6 +32,7 @@ class AdminController extends ApiController {
|
|||
private $credentialService;
|
||||
private $fileService;
|
||||
private $revisionService;
|
||||
private $deleteVaultRequestService;
|
||||
private $config;
|
||||
|
||||
public function __construct($AppName,
|
||||
|
@ -37,6 +42,7 @@ class AdminController extends ApiController {
|
|||
CredentialService $credentialService,
|
||||
FileService $fileService,
|
||||
CredentialRevisionService $revisionService,
|
||||
DeleteVaultRequestService $deleteVaultRequestService,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct(
|
||||
|
@ -50,30 +56,32 @@ class AdminController extends ApiController {
|
|||
$this->credentialService = $credentialService;
|
||||
$this->fileService = $fileService;
|
||||
$this->revisionService = $revisionService;
|
||||
$this->deleteVaultRequestService = $deleteVaultRequestService;
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
|
||||
public function searchUser($term){
|
||||
public function searchUser($term) {
|
||||
$um = \OC::$server->getUserManager();
|
||||
$results = array();
|
||||
$searchResult = $um->search($term);
|
||||
foreach ($searchResult as $user){
|
||||
foreach ($searchResult as $user) {
|
||||
array_push($results, array(
|
||||
"value" => $user->getUID(),
|
||||
"label" => $user->getDisplayName() . ' ('. $user->getBackendClassName() .')',
|
||||
"label" => $user->getDisplayName() . ' (' . $user->getBackendClassName() . ')',
|
||||
));
|
||||
}
|
||||
return new JSONResponse($results);
|
||||
}
|
||||
|
||||
public function moveCredentials($source_account, $destination_account){
|
||||
public function moveCredentials($source_account, $destination_account) {
|
||||
$vaults = $this->vaultService->getByUser($source_account);
|
||||
foreach ($vaults as $vault) {
|
||||
$credentials = $this->credentialService->getCredentialsByVaultId($vault->getId(), $source_account);
|
||||
foreach($credentials as $credential){
|
||||
foreach ($credentials as $credential) {
|
||||
$revisions = $this->revisionService->getRevisions($credential->getId());
|
||||
foreach ($revisions as $revision){
|
||||
foreach ($revisions as $revision) {
|
||||
$r = new CredentialRevision();
|
||||
$r->setId($revision['revision_id']);
|
||||
$r->setGuid($revision['guid']);
|
||||
|
@ -94,10 +102,87 @@ class AdminController extends ApiController {
|
|||
}
|
||||
|
||||
$files = $this->fileService->getFilesFromUser($source_account);
|
||||
foreach($files as $file){
|
||||
foreach ($files as $file) {
|
||||
$file->setUserId($destination_account);
|
||||
$this->fileService->updateFile($file);
|
||||
}
|
||||
return new JSONResponse(array('success'=> true));
|
||||
return new JSONResponse(array('success' => true));
|
||||
}
|
||||
|
||||
public function listRequests(){
|
||||
$requests = $this->deleteVaultRequestService->getDeleteRequests();
|
||||
$results = array();
|
||||
foreach($requests as $request){
|
||||
$r = $request->jsonSerialize();
|
||||
$r['displayName'] = Utils::getNameByUid($request->getRequestedBy());
|
||||
array_push($results, $r);
|
||||
}
|
||||
return new JSONResponse($results);
|
||||
}
|
||||
|
||||
public function acceptRequestDeletion($vault_guid, $requested_by){
|
||||
$req = $this->deleteVaultRequestService->getDeleteRequestForVault($vault_guid);
|
||||
try{
|
||||
$vault = $this->vaultService->getByGuid($vault_guid, $requested_by);
|
||||
} catch (\Exception $e){
|
||||
//Ignore
|
||||
}
|
||||
|
||||
if(isset($vault)){
|
||||
$credentials = $this->credentialService->getCredentialsByVaultId($vault->getId(), $requested_by);
|
||||
|
||||
foreach($credentials as $credential){
|
||||
$revisions = $this->revisionService->getRevisions($credential->getId());
|
||||
foreach($revisions as $revision){
|
||||
$this->revisionService->deleteRevision($revision['revision_id'], $requested_by);
|
||||
}
|
||||
$this->credentialService->deleteCredential($credential);
|
||||
}
|
||||
$this->vaultService->deleteVault($vault_guid, $requested_by);
|
||||
}
|
||||
$this->deleteVaultRequestService->removeDeleteRequestForVault($req);
|
||||
|
||||
return new JSONResponse(array('result' => true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function requestDeletion($vault_guid, $reason) {
|
||||
$req = $this->deleteVaultRequestService->getDeleteRequestForVault($vault_guid);
|
||||
if($req){
|
||||
return new JSONResponse('Already exists');
|
||||
}
|
||||
$vault = $this->vaultService->getByGuid($vault_guid, $this->userId);
|
||||
$result = false;
|
||||
if ($vault) {
|
||||
$delete_request = new DeleteVaultRequest();
|
||||
$delete_request->setRequestedBy($this->userId);
|
||||
$delete_request->setVaultGuid($vault->getGuid());
|
||||
$delete_request->setReason($reason);
|
||||
$delete_request->setCreated(time());
|
||||
$result = $this->deleteVaultRequestService->createRequest($delete_request);
|
||||
|
||||
}
|
||||
return new JSONResponse(array('result' => $result));
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function deleteRequestDeletion($vault_guid) {
|
||||
$delete_request = false;
|
||||
$result = false;
|
||||
try {
|
||||
$delete_request = $this->deleteVaultRequestService->getDeleteRequestForVault($vault_guid);
|
||||
} catch (\Exception $exception){
|
||||
// Ignore it
|
||||
}
|
||||
|
||||
if ($delete_request) {
|
||||
$this->deleteVaultRequestService->removeDeleteRequestForVault($delete_request);
|
||||
$result = true;
|
||||
}
|
||||
return new JSONResponse(array('result' => $result));
|
||||
}
|
||||
}
|
|
@ -347,6 +347,8 @@ class TranslationController extends ApiController {
|
|||
// templates/views/vaults.html
|
||||
'last.access' => $this->trans->t('Last accessed'),
|
||||
'never' => $this->trans->t('Never'),
|
||||
|
||||
|
||||
'no.vaults' => $this->trans->t('No vaults found, why not create one?'),
|
||||
'min.vault.key.strength' => $this->trans->t('Password strength must be at least: {{strength}}'),
|
||||
|
||||
|
@ -362,6 +364,20 @@ class TranslationController extends ApiController {
|
|||
'auto.logout' => $this->trans->t('Logout of this vault automatically after: '),
|
||||
'vault.decrypt' => $this->trans->t('Decrypt vault'),
|
||||
|
||||
'req.intro1' => $this->trans->t('Seems you lost the vault password and you\'re unable to login.'),
|
||||
'req.intro2' => $this->trans->t('If you want this vault removed you can request removal of the vault here.'),
|
||||
'req.intro3' => $this->trans->t('An admin then accept to the request (or not)'),
|
||||
|
||||
'request.deletion.warning' => $this->trans->t('After an admin destroy\'s this vault, all credentials will be lost'),
|
||||
'request.deletion.reason' => $this->trans->t('Reason to request deletion (optional):'),
|
||||
'request.deletion' => $this->trans->t('Request vault destruction'),
|
||||
'request.deletion.accept' => $this->trans->t('Yes, request an admin to destroy this vault'),
|
||||
'cancel.request.deletion' => $this->trans->t('Cancel destruction request'),
|
||||
'deletion.requested' => $this->trans->t('Vault destruction requested'),
|
||||
'deletion.removed' => $this->trans->t('Request removed'),
|
||||
'delete.request.pending' => $this->trans->t('Destruction request pending'),
|
||||
|
||||
|
||||
// templates/bookmarklet.php
|
||||
'http.warning' => $this->trans->t('Warning! Adding credentials over http can be insecure!'),
|
||||
'bm.active.vault' => $this->trans->t('Logged in to {{vault_name}}'),
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace OCA\Passman\Controller;
|
||||
|
||||
use OCA\Passman\Service\DeleteVaultRequestService;
|
||||
use OCA\Passman\Service\EncryptService;
|
||||
use OCA\Passman\Service\SettingsService;
|
||||
use OCA\Passman\Utility\NotFoundJSONResponse;
|
||||
|
@ -27,12 +28,14 @@ class VaultController extends ApiController {
|
|||
private $vaultService;
|
||||
private $credentialService;
|
||||
private $settings;
|
||||
private $deleteVaultRequestService;
|
||||
|
||||
public function __construct($AppName,
|
||||
IRequest $request,
|
||||
$UserId,
|
||||
VaultService $vaultService,
|
||||
CredentialService $credentialService,
|
||||
DeleteVaultRequestService $deleteVaultRequestService,
|
||||
SettingsService $settings) {
|
||||
parent::__construct(
|
||||
$AppName,
|
||||
|
@ -43,6 +46,7 @@ class VaultController extends ApiController {
|
|||
$this->userId = $UserId;
|
||||
$this->vaultService = $vaultService;
|
||||
$this->credentialService = $credentialService;
|
||||
$this->deleteVaultRequestService = $deleteVaultRequestService;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
|
@ -68,6 +72,7 @@ class VaultController extends ApiController {
|
|||
'public_sharing_key' => $vault->getPublicSharingKey(),
|
||||
'last_access' => $vault->getlastAccess(),
|
||||
'challenge_password' => $credential->{$secret_field}(),
|
||||
'delete_request_pending' => ($this->deleteVaultRequestService->getDeleteRequestForVault($vault->getGuid())) ? true : false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +114,8 @@ class VaultController extends ApiController {
|
|||
'public_sharing_key' => $vault->getPublicSharingKey(),
|
||||
'sharing_keys_generated' => $vault->getSharingKeysGenerated(),
|
||||
'vault_settings' => $vault->getVaultSettings(),
|
||||
'last_access' => $vault->getlastAccess()
|
||||
'last_access' => $vault->getlastAccess(),
|
||||
'delete_request_pending' => ($this->deleteVaultRequestService->getDeleteRequestForVault($vault->getGuid())) ? true : false
|
||||
);
|
||||
$result['credentials'] = $credentials;
|
||||
|
||||
|
|
|
@ -2,5 +2,12 @@
|
|||
padding: 5px; }
|
||||
#passwordSharingSettings #mover input[type="text"] {
|
||||
width: 350px; }
|
||||
#passwordSharingSettings #requests-table {
|
||||
width: 100%; }
|
||||
#passwordSharingSettings .link {
|
||||
color: #0066ff !important;
|
||||
cursor: pointer; }
|
||||
#passwordSharingSettings .link:hover {
|
||||
text-decoration: underline; }
|
||||
|
||||
/*# sourceMappingURL=admin.css.map */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAGM,wCAAE;EACA,OAAO,EAAE,GAAG;AAGhB,kDAAkB;EAChB,KAAK,EAAE,KAAK",
|
||||
"mappings": "AAGM,wCAAE;EACA,OAAO,EAAE,GAAG;AAGhB,kDAAkB;EAChB,KAAK,EAAE,KAAK;AAGhB,wCAAe;EACb,KAAK,EAAE,IAAI;AAIb,8BAAK;EACH,KAAK,EAAE,kBAA2B;EAClC,MAAM,EAAE,OAAO;AAEjB,oCAAW;EACT,eAAe,EAAE,SAAS",
|
||||
"sources": ["../sass/admin.scss"],
|
||||
"names": [],
|
||||
"file": "admin.css"
|
||||
|
|
|
@ -326,6 +326,13 @@
|
|||
display: inline-block; }
|
||||
.vault_wrapper .login_form .button {
|
||||
margin-top: 10px; }
|
||||
.vault_wrapper .reset_form {
|
||||
padding: 16px; }
|
||||
.vault_wrapper .reset_form label {
|
||||
margin-top: 20px;
|
||||
display: block; }
|
||||
.vault_wrapper .reset_form input[type="text"] {
|
||||
width: 100%; }
|
||||
.vault_wrapper .login_opts {
|
||||
margin-bottom: 10px; }
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -67,13 +67,19 @@
|
|||
.when('/vault/:vault_id/edit/:credential_id', {
|
||||
templateUrl: 'views/edit_credential.html',
|
||||
controller: 'CredentialEditCtrl'
|
||||
}).when('/vault/:vault_id/:credential_id/share', {
|
||||
templateUrl: 'views/share_credential.html',
|
||||
controller: 'ShareCtrl'
|
||||
}).when('/vault/:vault_id/:credential_id/revisions', {
|
||||
templateUrl: 'views/credential_revisions.html',
|
||||
controller: 'RevisionCtrl'
|
||||
})
|
||||
})
|
||||
.when('/vault/:vault_id/:credential_id/share', {
|
||||
templateUrl: 'views/share_credential.html',
|
||||
controller: 'ShareCtrl'
|
||||
})
|
||||
.when('/vault/:vault_id/:credential_id/revisions', {
|
||||
templateUrl: 'views/credential_revisions.html',
|
||||
controller: 'RevisionCtrl'
|
||||
})
|
||||
.when('/vault/:vault_id/request-deletion', {
|
||||
templateUrl: 'views/vault_req_deletion.html',
|
||||
controller: 'RequestDeleteCtrl'
|
||||
})
|
||||
.when('/vault/:vault_id/settings', {
|
||||
templateUrl: 'views/settings.html',
|
||||
controller: 'SettingsCtrl'
|
||||
|
|
|
@ -85,37 +85,36 @@
|
|||
prop: null
|
||||
}
|
||||
];
|
||||
|
||||
var tagMapper = function (t) {
|
||||
return {text: t};
|
||||
};
|
||||
var rowToCredential = function (row) {
|
||||
var _credential = PassmanImporter.newCredential();
|
||||
for(var k = 0; k < $scope.import_fields.length; k++){
|
||||
var field = $scope.import_fields[k];
|
||||
if(field){
|
||||
if(field === 'otp'){
|
||||
_credential.otp.secret = row[k]
|
||||
_credential.otp.secret = row[k];
|
||||
} else if(field === 'custom_field'){
|
||||
var key = ($scope.matched) ? $scope.parsed_csv[0][k] : 'Custom field '+ k;
|
||||
_credential.custom_fields.push({
|
||||
'label': key,
|
||||
'value': row[k],
|
||||
'secret': 0
|
||||
})
|
||||
});
|
||||
} else if(field === 'tags'){
|
||||
if( row[k]) {
|
||||
console.log(row, k);
|
||||
var tags = row[k].split(',');
|
||||
console.log();
|
||||
_credential.tags = tags.map(function (t) {
|
||||
console.log(t);
|
||||
return {text: t}
|
||||
});
|
||||
_credential.tags = tags.map(tagMapper);
|
||||
}
|
||||
} else{
|
||||
_credential[field] = row[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return _credential
|
||||
return _credential;
|
||||
};
|
||||
|
||||
|
||||
|
@ -204,6 +203,6 @@
|
|||
$scope.updateExample = function () {
|
||||
var start = ($scope.skipFirstRow) ? 1 : 0;
|
||||
$scope.inspectCredential($scope.parsed_csv[start]);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
}());
|
|
@ -151,6 +151,10 @@
|
|||
|
||||
};
|
||||
|
||||
$scope.requestDeletion = function (vault) {
|
||||
$location.path('/vault/' + vault.guid +'/request-deletion');
|
||||
};
|
||||
|
||||
var _loginToVault = function (vault, vault_key) {
|
||||
var _vault = angular.copy(vault);
|
||||
_vault.vaultKey = angular.copy(vault_key);
|
||||
|
|
61
js/app/controllers/vaultreqdeletion.js
Normal file
61
js/app/controllers/vaultreqdeletion.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name passmanApp.controller:MainCtrl
|
||||
* @description
|
||||
* # MainCtrl
|
||||
* Controller of the passmanApp
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.controller('RequestDeleteCtrl', ['$scope', '$location', '$http', '$routeParams', 'VaultService', 'NotificationService', '$translate',
|
||||
function ($scope, $location, $http, $routeParams, VaultService, NotificationService, $translate) {
|
||||
$scope.reason = '';
|
||||
VaultService.getVault({guid: $routeParams.vault_id}).then(function(vault){
|
||||
$scope.pending_deletion = vault.delete_request_pending;
|
||||
});
|
||||
|
||||
$scope.requestDeletion = function () {
|
||||
var queryUrl = OC.generateUrl('apps/passman/admin/request-deletion/'+ $routeParams.vault_id);
|
||||
var params = {
|
||||
reason: $scope.reason
|
||||
};
|
||||
|
||||
$http.post(queryUrl, params).then(function (response) {
|
||||
NotificationService.showNotification($translate.instant('deletion.requested'), 5000);
|
||||
$location.path('#/');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.removeRequestDeletion = function () {
|
||||
var queryUrl = OC.generateUrl('apps/passman/admin/request-deletion/' + $routeParams.vault_id);
|
||||
$http.delete(queryUrl).then(function (response) {
|
||||
NotificationService.showNotification($translate.instant('deletion.removed'), 5000);
|
||||
$location.path('#/');
|
||||
});
|
||||
};
|
||||
}]);
|
||||
}());
|
|
@ -39,7 +39,6 @@
|
|||
},
|
||||
|
||||
link: function (scope, element, attrs) {
|
||||
console.log(attrs.showLabel)
|
||||
scope.showLabel = (attrs.hasOwnProperty('showLabel'));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -59,7 +59,7 @@ $(document).ready(function () {
|
|||
|
||||
setAdminKey: function (key, value) {
|
||||
var request = $.ajax({
|
||||
url: this._baseUrl + '/' + key + '/' + value +'/admin1/admin2',
|
||||
url: this._baseUrl + '/' + key + '/' + value + '/admin1/admin2',
|
||||
method: 'POST'
|
||||
});
|
||||
request.done(function () {
|
||||
|
@ -72,7 +72,7 @@ $(document).ready(function () {
|
|||
});
|
||||
},
|
||||
getKey: function (key) {
|
||||
if(this._settings.hasOwnProperty(key)){
|
||||
if (this._settings.hasOwnProperty(key)) {
|
||||
return this._settings[key];
|
||||
}
|
||||
return false;
|
||||
|
@ -124,7 +124,7 @@ $(document).ready(function () {
|
|||
settings.setAdminKey('vault_key_strength', $(this).val());
|
||||
});
|
||||
|
||||
if($('form[name="passman_settings"]').length === 2){
|
||||
if ($('form[name="passman_settings"]').length === 2) {
|
||||
$('form[name="passman_settings"]')[1].remove();
|
||||
}
|
||||
|
||||
|
@ -132,10 +132,10 @@ $(document).ready(function () {
|
|||
'source_account': '',
|
||||
'destination_account': ''
|
||||
};
|
||||
$( ".username-autocomplete" ).autocomplete({
|
||||
$(".username-autocomplete").autocomplete({
|
||||
source: OC.generateUrl('apps/passman/admin/search'),
|
||||
minLength: 1,
|
||||
select: function( event, ui ) {
|
||||
select: function (event, ui) {
|
||||
accountMover[$(this).attr('id')] = ui.item.value;
|
||||
}
|
||||
});
|
||||
|
@ -144,10 +144,10 @@ $(document).ready(function () {
|
|||
var self = this;
|
||||
$('#moveStatus').hide();
|
||||
$(self).attr('disabled', 'disabled');
|
||||
$(self).html('<i class="fa fa-spinner fa-spin"></i> Moving...');
|
||||
if(accountMover.source_account && accountMover.destination_account){
|
||||
$(self).html('<i class="fa fa-spinner fa-spin"></i> ' + OC.L10N.translate('passman', 'Moving') + '...');
|
||||
if (accountMover.source_account && accountMover.destination_account) {
|
||||
$.post(OC.generateUrl('apps/passman/admin/move'), accountMover, function (data) {
|
||||
if(data.success){
|
||||
if (data.success) {
|
||||
$(self).removeAttr('disabled');
|
||||
$(self).html('Move');
|
||||
$('#moveStatus').fadeIn();
|
||||
|
@ -159,5 +159,74 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
|
||||
function format_date(date) {
|
||||
date = new Date(date);
|
||||
var month=date.getMonth();
|
||||
var year=date.getFullYear();
|
||||
var day=date.getDate();
|
||||
var hour=date.getHours();
|
||||
var minutes=date.getMinutes();
|
||||
var seconds=date.getSeconds();
|
||||
|
||||
month=month+1; //javascript date goes from 0 to 11
|
||||
if (month<10){
|
||||
month="0"+month; //adding the prefix
|
||||
}
|
||||
if (hour<10){
|
||||
hour="0"+hour; //adding the prefix
|
||||
}
|
||||
if (minutes<10){
|
||||
minutes="0"+minutes; //adding the prefix
|
||||
}
|
||||
if (seconds<10){
|
||||
seconds="0"+seconds; //adding the prefix
|
||||
}
|
||||
|
||||
|
||||
|
||||
return day+"-"+month+"-"+year+" "+hour+":"+minutes+":"+seconds;
|
||||
}
|
||||
|
||||
function acceptDeleteRequest (el, req) {
|
||||
if (!confirm(OC.L10N.translate('passman', "Are you really sure?\nThis will delete the vault and all credentials in it!"))) {
|
||||
return;
|
||||
}
|
||||
$.post(OC.generateUrl('apps/passman/admin/accept-delete-request'), req, function (result) {
|
||||
console.log(result);
|
||||
$(el).parent().parent().remove();
|
||||
})
|
||||
}
|
||||
|
||||
function ignoreDeleteRequest (el, req) {
|
||||
$.ajax({
|
||||
url: OC.generateUrl('apps/passman/admin/request-deletion/' + req.vault_guid),
|
||||
type: 'DELETE',
|
||||
success: function (result) {
|
||||
$(el).parent().parent().remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.get(OC.generateUrl('apps/passman/admin/delete-requests'), function (requests) {
|
||||
var table = $('#requests-table tbody');
|
||||
$.each(requests, function (k, request) {
|
||||
var accept = $('<span class="link">[Accept] </span>');
|
||||
accept.click(function () {
|
||||
var _self = this;
|
||||
acceptDeleteRequest(_self, request);
|
||||
});
|
||||
|
||||
var ignore = $('<span class="link">[Ignore]</span>');
|
||||
ignore.click(function () {
|
||||
var _self = this;
|
||||
ignoreDeleteRequest(_self, request);
|
||||
});
|
||||
|
||||
var cols = $('<td>' + request.id + '</td><td>' + request.displayName + '</td><td>' + request.reason + '</td><td>' + format_date(request.created * 1000 )+ '</td>');
|
||||
var actions = $('<td></td>').append(accept).append(ignore);
|
||||
table.append($('<tr></tr>').append(cols).append(actions));
|
||||
})
|
||||
});
|
||||
|
||||
$('#passman-tabs').tabs();
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
angular.module('templates-main', ['views/credential_revisions.html', 'views/edit_credential.html', 'views/partials/credential_template.html', 'views/partials/forms/edit_credential/basics.html', 'views/partials/forms/edit_credential/custom_fields.html', 'views/partials/forms/edit_credential/files.html', 'views/partials/forms/edit_credential/otp.html', 'views/partials/forms/edit_credential/password.html', 'views/partials/forms/settings/export.html', 'views/partials/forms/settings/general_settings.html', 'views/partials/forms/settings/generic_csv_import.html', 'views/partials/forms/settings/import.html', 'views/partials/forms/settings/password_settings.html', 'views/partials/forms/settings/sharing.html', 'views/partials/forms/settings/tool.html', 'views/partials/forms/share_credential/basics.html', 'views/partials/forms/share_credential/link_sharing.html', 'views/partials/password-meter.html', 'views/settings.html', 'views/share_credential.html', 'views/show_vault.html', 'views/vaults.html']);
|
||||
angular.module('templates-main', ['views/credential_revisions.html', 'views/edit_credential.html', 'views/partials/credential_template.html', 'views/partials/forms/edit_credential/basics.html', 'views/partials/forms/edit_credential/custom_fields.html', 'views/partials/forms/edit_credential/files.html', 'views/partials/forms/edit_credential/otp.html', 'views/partials/forms/edit_credential/password.html', 'views/partials/forms/settings/export.html', 'views/partials/forms/settings/general_settings.html', 'views/partials/forms/settings/generic_csv_import.html', 'views/partials/forms/settings/import.html', 'views/partials/forms/settings/password_settings.html', 'views/partials/forms/settings/sharing.html', 'views/partials/forms/settings/tool.html', 'views/partials/forms/share_credential/basics.html', 'views/partials/forms/share_credential/link_sharing.html', 'views/partials/password-meter.html', 'views/settings.html', 'views/share_credential.html', 'views/show_vault.html', 'views/vault_req_deletion.html', 'views/vaults.html']);
|
||||
|
||||
angular.module('views/credential_revisions.html', []).run(['$templateCache', function ($templateCache) {
|
||||
'use strict';
|
||||
|
@ -129,8 +129,14 @@ angular.module('views/show_vault.html', []).run(['$templateCache', function ($te
|
|||
' (settings.user_sharing_enabled === 1 || settings.user_sharing_enabled === \'1\' || settings.link_sharing_enabled === 1 || settings.link_sharing_enabled === \'1\')"><span class="fa fa-share"></span> {{ \'share\' | translate}}</button> <button class="button" ng-click="getRevisions(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.HISTORY)"><span class="fa fa-undo"></span> {{ \'revisions\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="recoverCredential(selectedCredential) && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-recycle"></span> {{\'recover\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="destroyCredential(selectedCredential)"><span class="fa fa-bomb"></span> {{\'destroy\' | translate}}</button></div></div></div></div><div class="share_popup" style="display: none">{{ \'sharereq.title\' | translate}}<br>{{ \'sharereq.line1\' | translate}}<br>{{ \'sharereq.line2\' | translate}} {{active_vault.vault_id}}<table class="table"><thead><tr><td>{{ \'label\' | translate}}</td><td>{{ \'permissions\' | translate}}</td><td>{{ \'received.from\' | translate}}</td><td>{{ \'date\' | translate}}</td></tr></thead><tr ng-repeat="share_request in incoming_share_requests" ng-if="share_request.target_vault_id == active_vault.vault_id"><td>{{share_request.credential_label}}</td><td>{{share_request.permissions}}</td><td>{{share_request.from_user_id}}</td><td>{{share_request.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td><td><span class="link" ng-click="acceptShareRequest(share_request)">{{ \'accept\' | translate}}</span> | <span class="link" ng-click="declineShareRequest(share_request)">{{ \'decline\' | translate}}</span></td></tr></table></div>');
|
||||
}]);
|
||||
|
||||
angular.module('views/vault_req_deletion.html', []).run(['$templateCache', function ($templateCache) {
|
||||
'use strict';
|
||||
$templateCache.put('views/vault_req_deletion.html',
|
||||
'<div class="vault_wrapper"><div class="reset_form" ng-show="!pending_deletion">{{ \'req.intro1\' | translate }}<br>{{ \'req.intro2\' | translate }}<br>{{ \'req.intro3\' | translate }}<br><br><b>{{ \'request.deletion.warning\' | translate}}</b><label>{{ \'request.deletion.reason\' | translate }}</label><input type="text" ng-model="reason" class="form-control"> <button class="button button-red" ng-click="requestDeletion()">{{ \'request.deletion.accept\' | translate }}</button> <a class="pull-right button button-geen" ng-href="#/">{{ \'cancel\' | translate}}</a></div><div class="reset_form" ng-show="pending_deletion"><button class="button button-red" ng-click="removeRequestDeletion()">Cancel destruction request</button> <a class="pull-right button button-geen" ng-href="#/">Cancel</a></div></div>');
|
||||
}]);
|
||||
|
||||
angular.module('views/vaults.html', []).run(['$templateCache', function ($templateCache) {
|
||||
'use strict';
|
||||
$templateCache.put('views/vaults.html',
|
||||
'<div class="vault_wrapper"><div class="vaults" ng-if="!list_selected_vault && !creating_vault"><div class="ui-select-container ui-select-bootstrap vaultlist"><ul><li ng-click="newVault()">+ Create a new vault</li><li ng-repeat="vault in vaults" ng-class="{\'selected\': vault == list_selected_vault }" ng-click="selectVault(vault)"><div><span class="ui-select-choices-row-inner"><div class="ng-binding ng-scope">{{vault.name}}</div><small class="ng-binding ng-scope">{{ \'created\' | translate}}: {{vault.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} | {{ \'last.access\' | translate}}: <span ng-if="vault.last_access > 0">{{vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span> <span ng-if="vault.last_access === 0">{{\'never\' | translate}}</span></small></span></div></li><li ng-if="vaults.length === 0">{{ \'no.vaults\' | translate}}</li></ul></div></div><div ng-if="creating_vault"><div class="login_form" ng-init="vault_name = \'\'; vault_key=\'\'; ">{{\'new.vault.name\' | translate}}<div><input type="text" ng-model="vault_name" required></div><div>{{ \'new.vault.pass\' | translate}} <input type="password" ng-model="vault_key" required><ng-password-meter password="vault_key" score="vault_key_score"></ng-password-meter></div><div>{{ \'new.vault.passr\' | translate}} <input type="password" ng-model="vault_key2" required></div><div ng-show="error || vault_key_score.score < minimal_value_key_strength" class="error"><ul><li ng-show="error">{{error}}</li><li ng-show="vault_key_score.score < minimal_value_key_strength">{{\'min.vault.key.strength\' | translate:required_score}}</li></ul></div><div><small>{{\'new.vault.sharing_key_notice\' | translate}}</small></div><div class="button_wrapper"><button class="button button-geen" ng-if="!creating_keys" ng-click="createVault(vault_name, vault_key, vault_key2)" ng-disabled="vault_key_score.score < minimal_value_key_strength || vault_key !== vault_key2 || vault_key === \'\'">{{ \'new.vault.create\' | translate }}</button><div class="button" ng-if="creating_keys"><span><i class="fa fa-spinner fa-spin"></i> {{creating_keys}}</span></div><div class="button button-red" ng-click="clearState()">{{ \'cancel\' | translate}}</div><div class="hidden">{{sharing_keys}}</div></div></div></div><div ng-if="list_selected_vault != false"><div class="vaultlist"><ul><li ng-click="clearState()">{{ \'go.back.vaults\' | translate }}</li></ul></div><div class="login_form"><div ng-show="error" class="error"><ul><li>{{error}}</li></ul></div>{{ \'input.vault.password\' | translate}} {{list_selected_vault.name}}<div class="pw-input"><input type="password" ng-model="vault_key" ng-enter="loginToVault(list_selected_vault, vault_key)"> <small class="last_access">{{\'last.access\' | translate}}: <span ng-if="list_selected_vault.last_access > 0">{{list_selected_vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span> <span ng-if="list_selected_vault.last_access === 0">Never</span></small></div><div class="login_opts"><div><label><input type="checkbox" ng-checked="default_vault" ng-click="toggleDefaultVault()"> {{ \'vault.default\' | translate}}</label></div><div><label><input type="checkbox" ng-checked="remember_vault_password" ng-click="toggleRememberPassword()"> {{ \'vault.auto.login\' | translate}}</label></div><div><label><input type="checkbox" ng-checked="auto_logout_timer" ng-click="toggleAutoLogout()"> {{ \'auto.logout\' | translate}}</label><select ng-model="logout_timer" ng-change="selectLogoutTimer(logout_timer)"><option value="0">Never</option><option value="30">30 minutes</option><option value="60">60 minutes</option><option value="90">90 minutes</option><option value="180">3 hour</option><option value="480">8 hour</option></select></div></div><div class="alert alert-danger" ng-show="vault_tries[list_selected_vault.guid].timeout !== 0" translate="vault.locked" translate-value-tries="{{ vault_tries[list_selected_vault.guid].tries }}" translate-value-time="{{ vault_tries[list_selected_vault.guid].timeout | toHHMMSS }}"></div><button class="button button-geen" ng-click="loginToVault(list_selected_vault, vault_key)" ng-disabled="vault_tries[list_selected_vault.guid].timeout !== 0">{{ \'vault.decrypt\' | translate}}</button></div></div></div>');
|
||||
'<div class="vault_wrapper"><div class="vaults" ng-if="!list_selected_vault && !creating_vault"><div class="ui-select-container ui-select-bootstrap vaultlist"><ul><li ng-click="newVault()">+ Create a new vault</li><li ng-repeat="vault in vaults" ng-class="{\'selected\': vault == list_selected_vault }" ng-click="selectVault(vault)"><div><span class="ui-select-choices-row-inner"><div class="ng-binding ng-scope">{{vault.name}} <span class="pull-right" style="color: #ce3702" ng-show="vault.delete_request_pending">{{ \'delete.request.pending\' | translate}}</span></div><small class="ng-binding ng-scope">{{ \'created\' | translate}}: {{vault.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} | {{ \'last.access\' | translate}}: <span ng-if="vault.last_access > 0">{{vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span> <span ng-if="vault.last_access === 0">{{\'never\' | translate}}</span></small></span></div></li><li ng-if="vaults.length === 0">{{ \'no.vaults\' | translate}}</li></ul></div></div><div ng-if="creating_vault"><div class="login_form" ng-init="vault_name = \'\'; vault_key=\'\'; ">{{\'new.vault.name\' | translate}}<div><input type="text" ng-model="vault_name" required></div><div>{{ \'new.vault.pass\' | translate}} <input type="password" ng-model="vault_key" required><ng-password-meter password="vault_key" score="vault_key_score"></ng-password-meter></div><div>{{ \'new.vault.passr\' | translate}} <input type="password" ng-model="vault_key2" required></div><div ng-show="error || vault_key_score.score < minimal_value_key_strength" class="error"><ul><li ng-show="error">{{error}}</li><li ng-show="vault_key_score.score < minimal_value_key_strength">{{\'min.vault.key.strength\' | translate:required_score}}</li></ul></div><div><small>{{\'new.vault.sharing_key_notice\' | translate}}</small></div><div class="button_wrapper"><button class="button button-geen" ng-if="!creating_keys" ng-click="createVault(vault_name, vault_key, vault_key2)" ng-disabled="vault_key_score.score < minimal_value_key_strength || vault_key !== vault_key2 || vault_key === \'\'">{{ \'new.vault.create\' | translate }}</button><div class="button" ng-if="creating_keys"><span><i class="fa fa-spinner fa-spin"></i> {{creating_keys}}</span></div><div class="button button-red" ng-click="clearState()">{{ \'cancel\' | translate}}</div><div class="hidden">{{sharing_keys}}</div></div></div></div><div ng-if="list_selected_vault != false"><div class="vaultlist"><ul><li ng-click="clearState()">{{ \'go.back.vaults\' | translate }}</li></ul></div><div class="login_form"><div ng-show="error" class="error"><ul><li>{{error}}</li></ul></div>{{ \'input.vault.password\' | translate}} {{list_selected_vault.name}}<div class="pw-input"><input type="password" ng-model="vault_key" ng-enter="loginToVault(list_selected_vault, vault_key)"> <small class="last_access">{{\'last.access\' | translate}}: <span ng-if="list_selected_vault.last_access > 0">{{list_selected_vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span> <span ng-if="list_selected_vault.last_access === 0">Never</span></small></div><div class="login_opts"><div><label><input type="checkbox" ng-checked="default_vault" ng-click="toggleDefaultVault()"> {{ \'vault.default\' | translate}}</label></div><div><label><input type="checkbox" ng-checked="remember_vault_password" ng-click="toggleRememberPassword()"> {{ \'vault.auto.login\' | translate}}</label></div><div><label><input type="checkbox" ng-checked="auto_logout_timer" ng-click="toggleAutoLogout()"> {{ \'auto.logout\' | translate}}</label><select ng-model="logout_timer" ng-change="selectLogoutTimer(logout_timer)"><option value="0">Never</option><option value="30">30 minutes</option><option value="60">60 minutes</option><option value="90">90 minutes</option><option value="180">3 hour</option><option value="480">8 hour</option></select></div></div><div class="alert alert-danger" ng-show="vault_tries[list_selected_vault.guid].timeout !== 0" translate="vault.locked" translate-value-tries="{{ vault_tries[list_selected_vault.guid].tries }}" translate-value-time="{{ vault_tries[list_selected_vault.guid].timeout | toHHMMSS }}"></div><button class="button button-geen" ng-click="loginToVault(list_selected_vault, vault_key)" ng-disabled="vault_tries[list_selected_vault.guid].timeout !== 0">{{ \'vault.decrypt\' | translate}}</button> <span ng-click="forgottenPassword = true;" style="margin-top: 10px; padding: 6px 12px" class="link pull-right" ng-show="!forgottenPassword">Forgot password?</span> <button ng-show="forgottenPassword" class="pull-right button button-red" ng-click="requestDeletion(list_selected_vault)"><span ng-show="list_selected_vault.delete_request_pending">{{ \'cancel.request.deletion\' | translate }}</span> <span ng-show="!list_selected_vault.delete_request_pending">{{ \'request.deletion\' | translate }}</span></button></div></div></div>');
|
||||
}]);
|
||||
|
|
67
lib/Db/DeleteVaultRequest.php
Normal file
67
lib/Db/DeleteVaultRequest.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Passman\Db;
|
||||
use \OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method integer getId()
|
||||
* @method void setId(integer $value)
|
||||
* @method void setVaultGuid(string $value)
|
||||
* @method string getVaultGuid()
|
||||
* @method void setReason(string $value)
|
||||
* @method string getReason()
|
||||
* @method void setRequestedBy(string $value)
|
||||
* @method string getRequestedBy()
|
||||
* @method void setCreated(integer $value)
|
||||
* @method integer getCreated()
|
||||
*/
|
||||
|
||||
|
||||
class DeleteVaultRequest extends Entity implements \JsonSerializable{
|
||||
|
||||
use EntityJSONSerializer;
|
||||
|
||||
protected $vaultGuid;
|
||||
protected $reason;
|
||||
protected $requestedBy;
|
||||
protected $created;
|
||||
|
||||
public function __construct() {
|
||||
// add types in constructor
|
||||
$this->addType('id', 'integer');
|
||||
$this->addType('created', 'integer');
|
||||
}
|
||||
/**
|
||||
* Turns entity attributes into an array
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'vault_guid' => $this->getVaultGuid(),
|
||||
'reason' => $this->getReason(),
|
||||
'requested_by' => $this->getRequestedBy(),
|
||||
'created' => $this->getCreated(),
|
||||
];
|
||||
}
|
||||
}
|
77
lib/Db/DeleteVaultRequestMapper.php
Normal file
77
lib/Db/DeleteVaultRequestMapper.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Passman\Db;
|
||||
|
||||
|
||||
use Icewind\SMB\Share;
|
||||
use OCA\Passman\Utility\Utils;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class DeleteVaultRequestMapper extends Mapper {
|
||||
const TABLE_NAME = 'passman_delete_vault_request';
|
||||
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, self::TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new enty in the db
|
||||
* @param DeleteVaultRequest $request
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function createRequest(DeleteVaultRequest $request){
|
||||
return $this->insert($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all delete requests
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function getDeleteRequests(){
|
||||
$q = "SELECT * FROM *PREFIX*" . self::TABLE_NAME;
|
||||
return $this->findEntities($q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request for an vault id
|
||||
* @param $vault_id integer The vault id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function getDeleteRequestsForVault($vault_guid){
|
||||
$q = "SELECT * FROM *PREFIX*" . self::TABLE_NAME .' WHERE `vault_guid` = ?';
|
||||
return $this->findEntity($q, [$vault_guid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given delete request
|
||||
* @param DeleteVaultRequest $shareRequest Request to delete
|
||||
* @return DeleteVaultRequest The deleted request
|
||||
*/
|
||||
public function removeDeleteVaultRequest(DeleteVaultRequest $request){
|
||||
return $this->delete($request);
|
||||
}
|
||||
|
||||
}
|
85
lib/Service/DeleteVaultRequestService.php
Normal file
85
lib/Service/DeleteVaultRequestService.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Passman\Service;
|
||||
|
||||
use OCA\Passman\Db\DeleteVaultRequest;
|
||||
use OCA\Passman\Db\DeleteVaultRequestMapper;
|
||||
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
|
||||
class DeleteVaultRequestService {
|
||||
|
||||
private $deleteVaultRequestMapper;
|
||||
|
||||
public function __construct(DeleteVaultRequestMapper $deleteVaultRequestMapper) {
|
||||
$this->deleteVaultRequestMapper = $deleteVaultRequestMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DeleteVaultRequest
|
||||
*
|
||||
* @param $request DeleteVaultRequest
|
||||
* @return \OCA\Passman\Db\DeleteVaultRequest
|
||||
*/
|
||||
public function createRequest(DeleteVaultRequest $request) {
|
||||
return $this->deleteVaultRequestMapper->insert($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DeleteVaultRequest
|
||||
*
|
||||
* @return \OCA\Passman\Db\DeleteVaultRequest[]
|
||||
*/
|
||||
public function getDeleteRequests() {
|
||||
return $this->deleteVaultRequestMapper->getDeleteRequests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DeleteVaultRequest
|
||||
*
|
||||
* @param $vault_id integer The vault id
|
||||
* @return bool | DeleteVaultRequest
|
||||
*/
|
||||
public function getDeleteRequestForVault($vault_guid) {
|
||||
try {
|
||||
$result = $this->deleteVaultRequestMapper->getDeleteRequestsForVault($vault_guid);
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DeleteVaultRequest
|
||||
*
|
||||
* @param $req DeleteVaultRequest
|
||||
* @return bool | DeleteVaultRequest
|
||||
*/
|
||||
public function removeDeleteRequestForVault(DeleteVaultRequest $req) {
|
||||
$this->deleteVaultRequestMapper->removeDeleteVaultRequest($req);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -50,4 +50,14 @@ class Utils {
|
|||
|
||||
return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uid
|
||||
* @return string
|
||||
*/
|
||||
public static function getNameByUid($uid){
|
||||
$um = \OC::$server->getUserManager();
|
||||
$u = $um->get($uid);
|
||||
return $u->getDisplayName();
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"grunt-replace": "^1.0.1",
|
||||
"html-minifier": "^3.0.2",
|
||||
"jasmine-core": "^2.5.2",
|
||||
"jshint-stylish": "^2.2.1",
|
||||
"karma": "^1.3.0",
|
||||
"karma-chrome-launcher": "^2.0.0",
|
||||
"karma-firefox-launcher": "^1.0.0",
|
||||
|
|
|
@ -9,4 +9,16 @@
|
|||
width: 350px;
|
||||
}
|
||||
}
|
||||
#requests-table{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.link{
|
||||
color: rgb(0, 102, 255) !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.link:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
|
@ -90,8 +90,20 @@
|
|||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.reset_form {
|
||||
padding: 16px;
|
||||
label{
|
||||
margin-top: 20px;
|
||||
display: block;
|
||||
}
|
||||
input[type="text"]{
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
}
|
||||
.login_opts{
|
||||
margin-bottom: 10px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ script('passman', 'app/controllers/settings');
|
|||
script('passman', 'app/controllers/import');
|
||||
script('passman', 'app/controllers/export');
|
||||
script('passman', 'app/controllers/generic-csv-importer');
|
||||
script('passman', 'app/controllers/vaultreqdeletion');
|
||||
script('passman', 'app/filters/range');
|
||||
script('passman', 'app/filters/propsfilter');
|
||||
script('passman', 'app/filters/byte');
|
||||
|
|
|
@ -11,10 +11,10 @@ style('passman', 'vendor/font-awesome/font-awesome.min');
|
|||
$checkVersion = OC::$server->getConfig()->getAppValue('passman', 'check_version', '1') === '1';
|
||||
$AppInstance = new App();
|
||||
$localVersion = $AppInstance->getAppInfo("passman")["version"];
|
||||
$githubVersion = $l->t('Unable to get version info');
|
||||
if ($checkVersion) {
|
||||
// get latest master version
|
||||
$version = false;
|
||||
$githubVersion = $l->t('Unable to get version info');
|
||||
|
||||
$url = 'https://raw.githubusercontent.com/nextcloud/passman/master/appinfo/info.xml';
|
||||
try {
|
||||
|
@ -68,7 +68,7 @@ $ciphers = openssl_get_cipher_methods();
|
|||
<a href="#mover"><?php p($l->t('Credential mover')); ?></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#tabs-3"><?php p($l->t('Vault delete requests')); ?></a>
|
||||
<a href="#tabs-3"><?php p($l->t('Vault destruction requests')); ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="general">
|
||||
|
@ -162,7 +162,21 @@ $ciphers = openssl_get_cipher_methods();
|
|||
|
||||
</div>
|
||||
<div id="tabs-3">
|
||||
Requests to delete vault
|
||||
<?php p($l->t('Requests to destroy vault')); ?>
|
||||
<table id="requests-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php p($l->t('Request ID')); ?></th>
|
||||
<th><?php p($l->t('Requested by')); ?></th>
|
||||
<th><?php p($l->t('Reason')); ?></th>
|
||||
<th><?php p($l->t('Created')); ?></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
30
templates/views/vault_req_deletion.html
Normal file
30
templates/views/vault_req_deletion.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<div class="vault_wrapper">
|
||||
<div class="reset_form" ng-show="!pending_deletion">
|
||||
{{ 'req.intro1' | translate }}<br/>
|
||||
{{ 'req.intro2' | translate }}<br/>
|
||||
{{ 'req.intro3' | translate }}<br/>
|
||||
<br/>
|
||||
|
||||
<b>{{ 'request.deletion.warning' | translate}}</b>
|
||||
|
||||
<label>{{ 'request.deletion.reason' | translate }}</label>
|
||||
<input type="text" ng-model="reason" class="form-control">
|
||||
<button class="button button-red"
|
||||
ng-click="requestDeletion()">
|
||||
{{ 'request.deletion.accept' | translate }}
|
||||
</button>
|
||||
<a class="pull-right button button-geen" ng-href="#/">
|
||||
{{ 'cancel' | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="reset_form" ng-show="pending_deletion">
|
||||
<button class="button button-red"
|
||||
ng-click="removeRequestDeletion()">
|
||||
Cancel destruction request
|
||||
</button>
|
||||
<a class="pull-right button button-geen" ng-href="#/">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
|
@ -9,7 +9,7 @@
|
|||
ng-click="selectVault(vault)">
|
||||
<div>
|
||||
<span class="ui-select-choices-row-inner">
|
||||
<div class="ng-binding ng-scope">{{vault.name}}</div>
|
||||
<div class="ng-binding ng-scope">{{vault.name}} <span class="pull-right" style="color: #ce3702;" ng-show="vault.delete_request_pending">{{ 'delete.request.pending' | translate}}</span></div>
|
||||
<small class="ng-binding ng-scope">
|
||||
|
||||
{{ 'created' | translate}}: {{vault.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
|
||||
|
@ -134,6 +134,11 @@
|
|||
ng-click="loginToVault(list_selected_vault, vault_key)" ng-disabled="vault_tries[list_selected_vault.guid].timeout !== 0">
|
||||
{{ 'vault.decrypt' | translate}}
|
||||
</button>
|
||||
<span ng-click="forgottenPassword = true;" style="margin-top: 10px; padding: 6px 12px;" class="link pull-right" ng-show="!forgottenPassword">Forgot password?</span>
|
||||
<button ng-show="forgottenPassword" class="pull-right button button-red" ng-click="requestDeletion(list_selected_vault)">
|
||||
<span ng-show="list_selected_vault.delete_request_pending">{{ 'cancel.request.deletion' | translate }}</span>
|
||||
<span ng-show="!list_selected_vault.delete_request_pending">{{ 'request.deletion' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue