mirror of
https://github.com/nextcloud/passman.git
synced 2024-09-20 06:46:20 +08:00
Add feature to move vaults to other account
This commit is contained in:
parent
ca4f6dfeaf
commit
514cb569fb
|
@ -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',
|
||||
|
|
|
@ -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'],
|
||||
]
|
||||
];
|
103
controller/admincontroller.php
Normal file
103
controller/admincontroller.php
Normal 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
6
css/admin.css
Normal 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
7
css/admin.css.map
Normal 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"
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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']);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
12
sass/admin.scss
Normal file
|
@ -0,0 +1,12 @@
|
|||
#passwordSharingSettings{
|
||||
#mover{
|
||||
table{
|
||||
td{
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
input[type="text"]{
|
||||
width: 350px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue