2016-12-22 10:00:51 +08:00
|
|
|
<?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;
|
|
|
|
|
2017-01-16 20:39:42 +08:00
|
|
|
use OCA\Passman\Db\Credential;
|
2016-12-22 10:00:51 +08:00
|
|
|
use OCA\Passman\Db\SharingACL;
|
2017-01-16 20:39:42 +08:00
|
|
|
use OCA\Passman\Service\EncryptService;
|
2017-01-07 02:42:58 +08:00
|
|
|
use OCA\Passman\Service\SettingsService;
|
2016-12-22 10:00:51 +08:00
|
|
|
use OCA\Passman\Utility\NotFoundJSONResponse;
|
2017-01-16 20:39:42 +08:00
|
|
|
use OCP\AppFramework\Db\DoesNotExistException;
|
2016-12-22 10:00:51 +08:00
|
|
|
use OCP\AppFramework\Http;
|
|
|
|
use OCP\AppFramework\Http\DataResponse;
|
|
|
|
use OCP\IRequest;
|
|
|
|
use OCP\AppFramework\Http\JSONResponse;
|
|
|
|
use OCP\AppFramework\ApiController;
|
|
|
|
use OCA\Passman\Service\CredentialService;
|
|
|
|
use OCA\Passman\Activity;
|
|
|
|
use OCA\Passman\Service\ActivityService;
|
|
|
|
use OCA\Passman\Service\CredentialRevisionService;
|
|
|
|
use OCA\Passman\Service\ShareService;
|
2017-01-07 02:42:58 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
class CredentialController extends ApiController {
|
|
|
|
private $userId;
|
|
|
|
private $credentialService;
|
|
|
|
private $activityService;
|
|
|
|
private $credentialRevisionService;
|
|
|
|
private $sharingService;
|
2017-01-07 02:42:58 +08:00
|
|
|
private $settings;
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
public function __construct($AppName,
|
|
|
|
IRequest $request,
|
|
|
|
$userId,
|
|
|
|
CredentialService $credentialService,
|
|
|
|
ActivityService $activityService,
|
|
|
|
CredentialRevisionService $credentialRevisionService,
|
2017-01-07 02:42:58 +08:00
|
|
|
ShareService $sharingService,
|
|
|
|
SettingsService $settings
|
2017-01-16 20:39:42 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
) {
|
2017-02-06 03:03:10 +08:00
|
|
|
parent::__construct(
|
|
|
|
$AppName,
|
|
|
|
$request,
|
|
|
|
'GET, POST, DELETE, PUT, PATCH, OPTIONS',
|
|
|
|
'Authorization, Content-Type, Accept',
|
|
|
|
86400);
|
2016-12-22 10:00:51 +08:00
|
|
|
$this->userId = $userId;
|
|
|
|
$this->credentialService = $credentialService;
|
|
|
|
$this->activityService = $activityService;
|
|
|
|
$this->credentialRevisionService = $credentialRevisionService;
|
|
|
|
$this->sharingService = $sharingService;
|
2017-01-07 02:42:58 +08:00
|
|
|
$this->settings = $settings;
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
|
|
|
|
2017-01-07 02:42:58 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function createCredential($changed, $created,
|
|
|
|
$credential_id, $custom_fields, $delete_time,
|
|
|
|
$description, $email, $expire_time, $favicon, $files, $guid,
|
|
|
|
$hidden, $label, $otp, $password, $renew_interval,
|
2019-05-13 01:16:48 +08:00
|
|
|
$tags, $url, $username, $vault_id, $compromised) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$credential = array(
|
|
|
|
'credential_id' => $credential_id,
|
|
|
|
'guid' => $guid,
|
|
|
|
'user_id' => $this->userId,
|
|
|
|
'vault_id' => $vault_id,
|
|
|
|
'label' => $label,
|
|
|
|
'description' => $description,
|
|
|
|
'created' => $created,
|
|
|
|
'changed' => $changed,
|
|
|
|
'tags' => $tags,
|
|
|
|
'email' => $email,
|
|
|
|
'username' => $username,
|
|
|
|
'password' => $password,
|
|
|
|
'url' => $url,
|
|
|
|
'favicon' => $favicon,
|
|
|
|
'renew_interval' => $renew_interval,
|
|
|
|
'expire_time' => $expire_time,
|
|
|
|
'delete_time' => $delete_time,
|
|
|
|
'files' => $files,
|
|
|
|
'custom_fields' => $custom_fields,
|
|
|
|
'otp' => $otp,
|
|
|
|
'hidden' => $hidden,
|
2019-05-13 01:16:48 +08:00
|
|
|
'compromised' => $compromised
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
);
|
2017-01-16 20:39:42 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
$credential = $this->credentialService->createCredential($credential);
|
|
|
|
$link = ''; // @TODO create direct link to credential
|
2017-01-07 02:42:58 +08:00
|
|
|
if (!$credential->getHidden()) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$this->activityService->add(
|
|
|
|
Activity::SUBJECT_ITEM_CREATED_SELF, array($label, $this->userId),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_ACTION);
|
|
|
|
}
|
2018-12-19 14:31:49 +08:00
|
|
|
|
|
|
|
return new JSONResponse($this->credentialService->getCredentialByGUID($credential->getGuid()));
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function getCredential($credential_guid) {
|
2017-01-16 20:39:42 +08:00
|
|
|
$credential = $this->credentialService->getCredentialByGUID($credential_guid, $this->userId);
|
|
|
|
return new JSONResponse($credential);
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function updateCredential($changed, $created,
|
|
|
|
$credential_id, $custom_fields, $delete_time, $credential_guid,
|
2018-12-19 14:31:49 +08:00
|
|
|
$description, $email, $expire_time, $icon, $files, $guid,
|
2016-12-22 10:00:51 +08:00
|
|
|
$hidden, $label, $otp, $password, $renew_interval,
|
2019-05-13 01:16:48 +08:00
|
|
|
$tags, $url, $username, $vault_id, $revision_created, $shared_key, $acl, $unshare_action, $set_share_key, $skip_revision, $compromised) {
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
|
2017-01-16 20:39:42 +08:00
|
|
|
$storedCredential = $this->credentialService->getCredentialByGUID($credential_guid);
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
$credential = array(
|
|
|
|
'credential_id' => $credential_id,
|
|
|
|
'guid' => $guid,
|
|
|
|
'label' => $label,
|
|
|
|
'description' => $description,
|
|
|
|
'created' => $created,
|
|
|
|
'changed' => $changed,
|
|
|
|
'vault_id' => $vault_id,
|
|
|
|
'tags' => $tags,
|
|
|
|
'email' => $email,
|
|
|
|
'username' => $username,
|
|
|
|
'password' => $password,
|
|
|
|
'url' => $url,
|
2018-12-19 14:31:49 +08:00
|
|
|
'icon' => json_encode($icon),
|
2016-12-22 10:00:51 +08:00
|
|
|
'renew_interval' => $renew_interval,
|
|
|
|
'expire_time' => $expire_time,
|
|
|
|
'files' => $files,
|
|
|
|
'custom_fields' => $custom_fields,
|
|
|
|
'delete_time' => $delete_time,
|
|
|
|
'hidden' => $hidden,
|
|
|
|
'otp' => $otp,
|
2019-05-13 01:16:48 +08:00
|
|
|
'user_id' => $storedCredential->getUserId(),
|
|
|
|
'compromised' => $compromised
|
2016-12-22 10:00:51 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
|
2017-01-07 02:42:58 +08:00
|
|
|
if (!hash_equals($storedCredential->getUserId(), $this->userId)) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$acl = $this->sharingService->getCredentialAclForUser($this->userId, $storedCredential->getGuid());
|
|
|
|
if ($acl->hasPermission(SharingACL::WRITE)) {
|
|
|
|
$credential['shared_key'] = $storedCredential->getSharedKey();
|
|
|
|
} else {
|
|
|
|
return new DataResponse(['msg' => 'Not authorized'], Http::STATUS_UNAUTHORIZED);
|
|
|
|
}
|
2017-01-16 20:39:42 +08:00
|
|
|
if (!$this->settings->isEnabled('user_sharing_enabled')) {
|
2017-01-07 02:42:58 +08:00
|
|
|
return new DataResponse(['msg' => 'Not authorized'], Http::STATUS_UNAUTHORIZED);
|
|
|
|
}
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
2017-01-07 02:42:58 +08:00
|
|
|
|
2017-01-16 20:39:42 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
$link = ''; // @TODO create direct link to credential
|
|
|
|
if ($revision_created) {
|
|
|
|
$activity = 'item_apply_revision';
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity . '_self', array($label, $this->userId, $revision_created),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_ACTION);
|
2017-01-07 02:42:58 +08:00
|
|
|
} else if (($storedCredential->getDeleteTime() === 0) && (int)$delete_time > 0) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$activity = 'item_deleted';
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity . '_self', array($label, $this->userId),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_ACTION);
|
2017-01-07 02:42:58 +08:00
|
|
|
} else if (($storedCredential->getDeleteTime() > 0) && (int)$delete_time === 0) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$activity = 'item_recovered';
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity . '_self', array($label, $this->userId),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_ACTION);
|
|
|
|
} else if ($label !== $storedCredential->getLabel()) {
|
|
|
|
$activity = 'item_renamed';
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity . '_self', array($storedCredential->getLabel(), $label, $this->userId),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_RENAMED);
|
|
|
|
} else {
|
|
|
|
$activity = 'item_edited';
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity . '_self', array($label, $this->userId),
|
|
|
|
'', array(),
|
|
|
|
$link, $this->userId, Activity::TYPE_ITEM_ACTION);
|
|
|
|
}
|
|
|
|
$acl_list = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
$acl_list = $this->sharingService->getCredentialAclList($storedCredential->getGuid());
|
2017-01-07 02:42:58 +08:00
|
|
|
} catch (\Exception $exception) {
|
2016-12-22 10:00:51 +08:00
|
|
|
// Just check if we have an acl list
|
|
|
|
}
|
|
|
|
if (!empty($acl_list)) {
|
|
|
|
$params = array();
|
|
|
|
switch ($activity) {
|
|
|
|
case 'item_recovered':
|
|
|
|
case 'item_deleted':
|
|
|
|
case 'item_edited':
|
|
|
|
$params = array($credential['label'], $this->userId);
|
|
|
|
break;
|
|
|
|
case 'item_apply_revision':
|
|
|
|
$params = array($credential['label'], $this->userId, $revision_created);
|
|
|
|
break;
|
|
|
|
case 'item_renamed':
|
|
|
|
$params = array($storedCredential->getLabel(), $label, $this->userId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($acl_list as $sharingACL) {
|
|
|
|
$target_user = $sharingACL->getUserId();
|
2017-01-07 02:42:58 +08:00
|
|
|
if ($target_user === $this->userId) {
|
2016-12-22 10:00:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$this->activityService->add(
|
|
|
|
$activity, $params,
|
|
|
|
'', array(),
|
|
|
|
$link, $target_user, Activity::TYPE_ITEM_ACTION);
|
|
|
|
}
|
2017-01-07 02:42:58 +08:00
|
|
|
if (!hash_equals($this->userId, $storedCredential->getUserId())) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$this->activityService->add(
|
|
|
|
$activity, $params,
|
|
|
|
'', array(),
|
|
|
|
$link, $storedCredential->getUserId(), Activity::TYPE_ITEM_ACTION);
|
|
|
|
}
|
|
|
|
}
|
2017-01-07 02:42:58 +08:00
|
|
|
if ($set_share_key === true) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$storedCredential->setSharedKey($shared_key);
|
|
|
|
$credential['shared_key'] = $shared_key;
|
|
|
|
}
|
2017-01-07 02:42:58 +08:00
|
|
|
if ($unshare_action === true) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$storedCredential->setSharedKey('');
|
|
|
|
$credential['shared_key'] = '';
|
|
|
|
}
|
2017-01-16 20:39:42 +08:00
|
|
|
|
|
|
|
if (!isset($credential['shared_key'])) {
|
|
|
|
$credential['shared_key'] = $storedCredential->getSharedKey();
|
|
|
|
}
|
|
|
|
|
2017-01-07 02:42:58 +08:00
|
|
|
if (!$skip_revision) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$this->credentialRevisionService->createRevision($storedCredential, $storedCredential->getUserId(), $credential_id, $this->userId);
|
|
|
|
}
|
2017-01-16 20:39:42 +08:00
|
|
|
|
2016-12-22 10:00:51 +08:00
|
|
|
$credential = $this->credentialService->updateCredential($credential);
|
|
|
|
|
2018-12-19 14:31:49 +08:00
|
|
|
return new JSONResponse($this->credentialService->getCredentialByGUID($credential->getGuid()));
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function deleteCredential($credential_guid) {
|
2017-01-16 20:39:42 +08:00
|
|
|
try {
|
|
|
|
$credential = $this->credentialService->getCredentialByGUID($credential_guid, $this->userId);
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
return new NotFoundJSONResponse();
|
|
|
|
}
|
2017-02-06 03:03:10 +08:00
|
|
|
if ($credential instanceof Credential) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$result = $this->credentialService->deleteCredential($credential);
|
2017-02-06 03:03:10 +08:00
|
|
|
//print_r($credential);
|
2017-01-16 20:39:42 +08:00
|
|
|
$this->deleteCredentialParts($credential);
|
2016-12-22 10:00:51 +08:00
|
|
|
} else {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
return new JSONResponse($result);
|
|
|
|
}
|
|
|
|
|
2017-01-16 20:39:42 +08:00
|
|
|
/**
|
|
|
|
* Delete leftovers from a credential
|
|
|
|
* @param Credential $credential
|
|
|
|
*/
|
|
|
|
private function deleteCredentialParts(Credential $credential) {
|
|
|
|
$this->activityService->add(
|
|
|
|
'item_destroyed_self', array($credential->getLabel()),
|
|
|
|
'', array(),
|
|
|
|
'', $this->userId, Activity::TYPE_ITEM_ACTION);
|
|
|
|
$this->sharingService->unshareCredential($credential->getGuid());
|
|
|
|
foreach ($this->credentialRevisionService->getRevisions($credential->getId()) as $revision) {
|
2017-02-24 01:31:00 +08:00
|
|
|
$id = $revision['revision_id'];
|
2017-02-07 02:20:31 +08:00
|
|
|
if(isset($id)){
|
|
|
|
$this->credentialRevisionService->deleteRevision($id, $this->userId);
|
|
|
|
}
|
2017-01-16 20:39:42 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function getRevision($credential_guid) {
|
2017-01-07 02:42:58 +08:00
|
|
|
try {
|
|
|
|
$credential = $this->credentialService->getCredentialByGUID($credential_guid);
|
|
|
|
} catch (\Exception $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();
|
|
|
|
}
|
|
|
|
}
|
2016-12-22 10:00:51 +08:00
|
|
|
|
|
|
|
return new JSONResponse($result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
|
|
|
public function deleteRevision($credential_id, $revision_id) {
|
|
|
|
$result = $this->credentialRevisionService->deleteRevision($revision_id, $this->userId);
|
|
|
|
return new JSONResponse($result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @NoAdminRequired
|
2016-12-27 18:32:50 +08:00
|
|
|
* @NoCSRFRequired
|
2016-12-22 10:00:51 +08:00
|
|
|
*/
|
2017-02-24 01:31:00 +08:00
|
|
|
public function updateRevision($revision_id, $credential_data) {
|
2016-12-22 10:00:51 +08:00
|
|
|
$revision = null;
|
2017-01-07 02:42:58 +08:00
|
|
|
try {
|
2016-12-22 10:00:51 +08:00
|
|
|
$revision = $this->credentialRevisionService->getRevision($revision_id);
|
2017-01-07 02:42:58 +08:00
|
|
|
} catch (\Exception $exception) {
|
2017-02-24 01:31:00 +08:00
|
|
|
return new JSONResponse(array());
|
2016-12-22 10:00:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
$revision->setCredentialData($credential_data);
|
|
|
|
|
|
|
|
$this->credentialRevisionService->updateRevision($revision);
|
|
|
|
return new JSONResponse(array());
|
|
|
|
}
|
|
|
|
}
|