Add feature to move vaults to other account

This commit is contained in:
brantje 2017-02-19 15:13:40 +01:00
parent ca4f6dfeaf
commit 514cb569fb
No known key found for this signature in database
GPG key ID: 5FF1D117F918687F
12 changed files with 335 additions and 88 deletions

View file

@ -75,6 +75,13 @@ module.exports = function (grunt) {
src: ["**/public-page.scss"],
dest: "css",
ext: ".css"
},
{
expand: true,
cwd: "sass",
src: ["**/admin.scss"],
dest: "css",
ext: ".css"
}
]
}
@ -132,6 +139,7 @@ module.exports = function (grunt) {
'!css/app.*',
'css/bookmarklet.css',
'css/public-page.css',
'css/admin.css',
'!dist/*',
'!dist/*/**',
'!dist',

View file

@ -84,5 +84,9 @@ 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'],
//Admin routes
['name' => 'admin#searchUser', 'url' => '/admin/search', 'verb' => 'GET'],
['name' => 'admin#moveCredentials', 'url' => '/admin/move', 'verb' => 'POST'],
]
];

View file

@ -0,0 +1,103 @@
<?php
/**
* Nextcloud - passman
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Sander Brand <brantje@gmail.com>
* @copyright Sander Brand 2016
*/
namespace OCA\Passman\Controller;
use OCA\Passman\Db\CredentialRevision;
use OCA\Passman\Service\CredentialRevisionService;
use OCA\Passman\Service\FileService;
use OCA\Passman\Service\VaultService;
use OCP\IConfig;
use OCP\IRequest;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\ApiController;
use OCA\Passman\Service\CredentialService;
use \OCP\App;
class AdminController extends ApiController {
private $userId;
private $vaultService;
private $credentialService;
private $fileService;
private $revisionService;
private $config;
public function __construct($AppName,
IRequest $request,
$UserId,
VaultService $vaultService,
CredentialService $credentialService,
FileService $fileService,
CredentialRevisionService $revisionService,
IConfig $config
) {
parent::__construct(
$AppName,
$request,
'GET, POST, DELETE, PUT, PATCH, OPTIONS',
'Authorization, Content-Type, Accept',
86400);
$this->userId = $UserId;
$this->vaultService = $vaultService;
$this->credentialService = $credentialService;
$this->fileService = $fileService;
$this->revisionService = $revisionService;
$this->config = $config;
}
public function searchUser($term){
$um = \OC::$server->getUserManager();
$results = array();
$searchResult = $um->search($term);
foreach ($searchResult as $user){
array_push($results, array(
"value" => $user->getUID(),
"label" => $user->getDisplayName() . ' ('. $user->getBackendClassName() .')',
));
}
return new JSONResponse($results);
}
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){
$revisions = $this->revisionService->getRevisions($credential->getId());
foreach ($revisions as $revision){
$r = new CredentialRevision();
$r->setId($revision['revision_id']);
$r->setGuid($revision['guid']);
$r->setCredentialId($credential->getId());
$r->setUserId($destination_account);
$r->setCreated($revision['created']);
$r->setCredentialData(base64_encode(json_encode($revision['credential_data'])));
$r->setEditedBy($revision['edited_by']);
$this->revisionService->updateRevision($r);
}
$c = $credential->jsonSerialize();
$c['user_id'] = $destination_account;
$this->credentialService->updateCredential($c, true);
}
$vault->setUserId($destination_account);
$this->vaultService->updateVault($vault);
}
$files = $this->fileService->getFilesFromUser($source_account);
foreach($files as $file){
$file->setUserId($destination_account);
$this->fileService->updateFile($file);
}
return new JSONResponse(array('success'=> true));
}
}

6
css/admin.css Normal file
View file

@ -0,0 +1,6 @@
#passwordSharingSettings #mover table td {
padding: 5px; }
#passwordSharingSettings #mover input[type="text"] {
width: 350px; }
/*# sourceMappingURL=admin.css.map */

7
css/admin.css.map Normal file
View file

@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "AAGM,wCAAE;EACA,OAAO,EAAE,GAAG;AAGhB,kDAAkB;EAChB,KAAK,EAAE,KAAK",
"sources": ["../sass/admin.scss"],
"names": [],
"file": "admin.css"
}

View file

@ -21,7 +21,6 @@
*/
$(document).ready(function () {
var Settings = function (baseUrl) {
this._baseUrl = baseUrl;
this._settings = [];
@ -86,7 +85,6 @@ $(document).ready(function () {
var settings = new Settings(OC.generateUrl('apps/passman/api/v2/settings'));
settings.load();
// ADMIN SETTINGS
// fill the boxes
@ -130,4 +128,36 @@ $(document).ready(function () {
$('form[name="passman_settings"]')[1].remove();
}
var accountMover = {
'source_account': '',
'destination_account': ''
};
$( ".username-autocomplete" ).autocomplete({
source: OC.generateUrl('apps/passman/admin/search'),
minLength: 1,
select: function( event, ui ) {
accountMover[$(this).attr('id')] = ui.item.value;
}
});
$('#move_credentials').click(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){
$.post(OC.generateUrl('apps/passman/admin/move'), accountMover, function (data) {
if(data.success){
$(self).removeAttr('disabled');
$(self).html('Move');
$('#moveStatus').fadeIn();
setTimeout(function () {
$('#moveStatus').fadeOut();
}, 3500)
}
});
}
});
$('#passman-tabs').tabs();
});

View file

@ -148,15 +148,18 @@ class CredentialMapper extends Mapper {
* Update a credential
*
* @param $raw_credential array An array containing all the credential fields
* @param $useRawUser bool
* @return Credential The updated credential
*/
public function updateCredential($raw_credential) {
public function updateCredential($raw_credential, $useRawUser) {
$original = $this->getCredentialByGUID($raw_credential['guid']);
$uid = ($useRawUser) ? $raw_credential['user_id'] : $original->getUserId();
$credential = new Credential();
$credential->setId($original->getId());
$credential->setGuid($original->getGuid());
$credential->setVaultId($original->getVaultId());
$credential->setUserId($original->getUserId());
$credential->setUserId($uid);
$credential->setLabel($raw_credential['label']);
$credential->setDescription($raw_credential['description']);
$credential->setCreated($original->getCreated());
@ -174,6 +177,7 @@ class CredentialMapper extends Mapper {
$credential->setOtp($raw_credential['otp']);
$credential->setHidden($raw_credential['hidden']);
$credential->setDeleteTime($raw_credential['delete_time']);
if (isset($raw_credential['shared_key'])) {
$credential->setSharedKey($raw_credential['shared_key']);
}

View file

@ -112,4 +112,19 @@ class FileMapper extends Mapper {
public function updateFile(File $file) {
return $this->update($file);
}
/**
* @param $user_id
* @return File[]
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result
*/
public function getFilesFromUser($user_id) {
$sql = 'SELECT * FROM `*PREFIX*passman_files` ' .
'WHERE `user_id` = ?';
$params = [$user_id];
return $this->findEntities($sql, $params);
}
}

View file

@ -61,12 +61,13 @@ class CredentialService {
/**
* Update credential
*
* @param $credential array
* @param $credential array | Credential
* @param $useRawUser bool
* @return Credential
*/
public function updateCredential($credential) {
public function updateCredential($credential, $useRawUser = false) {
$credential = $this->encryptService->encryptCredential($credential);
return $this->credentialMapper->updateCredential($credential);
return $this->credentialMapper->updateCredential($credential, $useRawUser);
}
/**

View file

@ -101,4 +101,18 @@ class FileService {
return $this->fileMapper->updateFile($file);
}
/**
* Update file
*
* @param string $userId
* @return File[]
*/
public function getFilesFromUser($userId){
$files = $this->fileMapper->getFilesFromUser($userId);
$results = array();
foreach ($files as $file){
array_push($results, $this->encryptService->decryptFile($file));
}
return $results;
}
}

12
sass/admin.scss Normal file
View file

@ -0,0 +1,12 @@
#passwordSharingSettings{
#mover{
table{
td{
padding: 5px;
}
}
input[type="text"]{
width: 350px;
}
}
}

View file

@ -5,6 +5,9 @@ use \OCP\App;
script('passman', 'settings-admin');
style('passman', 'admin');
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"];
@ -41,86 +44,126 @@ $ciphers = openssl_get_cipher_methods();
?>
<div id="passwordSharingSettings" class="followup section">
<form name="passman_settings">
<h2><?php p($l->t('Passman Settings')); ?></h2>
<?php
if ($checkVersion) {
p($l->t('Github version:') . ' ' . $githubVersion);
print '<br />';
} ?>
Local version: <?php p($localVersion); ?><br/>
<?php
if ($checkVersion && version_compare($githubVersion, $localVersion) === 1) {
p($l->t('A newer version of passman is available'));
}
?>
<h3><?php p($l->t('Sharing')); ?></h3>
<p>
<input type="checkbox" name="passman_link_sharing_enabled"
id="passman_link_sharing_enabled" class="checkbox"
value="1"/>
<label for="passman_link_sharing_enabled">
<?php p($l->t('Allow users on this server to share passwords with a link')); ?>
</label>
</p>
<h2><?php p($l->t('Passman Settings')); ?></h2>
<?php
if ($checkVersion) {
p($l->t('Github version:') . ' ' . $githubVersion);
print '<br />';
} ?>
Local version: <?php p($localVersion); ?><br/>
<?php
if ($checkVersion && version_compare($githubVersion, $localVersion) === 1) {
p($l->t('A newer version of passman is available'));
}
?>
<div id="passman-tabs">
<ul>
<li>
<a href="#general"><?php p($l->t('General settings')); ?></a>
</li>
<li>
<a href="#sharing"><?php p($l->t('Password sharing')); ?></a>
</li>
<li>
<a href="#mover"><?php p($l->t('Credential mover')); ?></a>
</li>
<li>
<a href="#tabs-3"><?php p($l->t('Vault delete requests')); ?></a>
</li>
</ul>
<div id="general">
<form name="passman_settings">
<p>
<input type="checkbox" name="check_version"
id="passman_check_version" class="checkbox"
value="0"/>
<label for="passman_check_version">
<?php p($l->t('Check for new versions')); ?>
</label>
</p>
<p>
<input type="checkbox" name="https_check"
id="passman_https_check" class="checkbox"
value="0"/>
<label for="passman_https_check">
<?php p($l->t('Enable HTTPS check')); ?>
</label>
</p>
<p>
<input type="checkbox" name="disable_contextmenu"
id="passman_disable_contextmenu" class="checkbox"
value="0"/>
<label for="passman_disable_contextmenu">
<?php p($l->t('Disable context menu')); ?>
</label>
</p>
<p>
<input type="checkbox" name="passman_disable_debugger"
id="passman_disable_debugger" class="checkbox"
value="0"/>
<label for="passman_disable_debugger">
<?php p($l->t('Disable javascript debugger')); ?>
</label>
</p>
<p>
<label for="vault_key_strength">Minimum vault key
strength:</label>
<select name="vault_key_strength" id="vault_key_strength">
<option value="0">
Poor
</option>
<option value="2">
Weak
</option>
<option value="3">
Good
</option>
<option value="4">
Strong
</option>
</select>
</p>
</form>
</div>
<div id="sharing">
<p>
<input type="checkbox" name="passman_link_sharing_enabled"
id="passman_link_sharing_enabled" class="checkbox"
value="1"/>
<label for="passman_link_sharing_enabled">
<?php p($l->t('Allow users on this server to share passwords with a link')); ?>
</label>
</p>
<p>
<input type="checkbox" name="passman_sharing_enabled"
id="passman_sharing_enabled" class="checkbox"
value="1"/>
<label for="passman_sharing_enabled">
<?php p($l->t('Allow users on this server to share passwords with other users')); ?>
</label>
</p>
<h3><?php p($l->t('General')); ?></h3>
<p>
<input type="checkbox" name="check_version"
id="passman_check_version" class="checkbox"
value="0"/>
<label for="passman_check_version">
<?php p($l->t('Check for new versions')); ?>
</label>
</p>
<p>
<input type="checkbox" name="https_check"
id="passman_https_check" class="checkbox"
value="0"/>
<label for="passman_https_check">
<?php p($l->t('Enable HTTPS check')); ?>
</label>
</p>
<p>
<input type="checkbox" name="disable_contextmenu"
id="passman_disable_contextmenu" class="checkbox"
value="0"/>
<label for="passman_disable_contextmenu">
<?php p($l->t('Disable context menu')); ?>
</label>
</p>
<p>
<input type="checkbox" name="passman_disable_debugger"
id="passman_disable_debugger" class="checkbox"
value="0"/>
<label for="passman_disable_debugger">
<?php p($l->t('Disable javascript debugger')); ?>
</label>
</p>
<p>
<label for="vault_key_strength">Minimum vault key strength:</label>
<select name="vault_key_strength" id="vault_key_strength">
<option value="0">
Poor
</option>
<option value="2">
Weak
</option>
<option value="3">
Good
</option>
<option value="4">
Strong
</option>
</select>
</p>
</form>
<p>
<input type="checkbox" name="passman_sharing_enabled"
id="passman_sharing_enabled" class="checkbox"
value="1"/>
<label for="passman_sharing_enabled">
<?php p($l->t('Allow users on this server to share passwords with other users')); ?>
</label>
</p>
</div>
<div id="mover">
<p><?php p($l->t('Move credentials from one account to another')); ?></p>
<br/>
<table class="table">
<tr>
<td><?php p($l->t('Source account')); ?> </td>
<td><input class="username-autocomplete" type="text" id="source_account" name="source_account"></td>
</tr>
<tr>
<td><?php p($l->t('Destination account')); ?> </td>
<td><input class="username-autocomplete" type="text" id="destination_account" name="destination_account"></td>
</tr>
</table>
<button class="success" id="move_credentials">Move</button>
<span id="moveStatus" style="display: none;"><?php p($l->t('Credentials moved!')); ?></span>
</div>
<div id="tabs-3">
Requests to delete vault
</div>
</div>
</div>