Sharing action api

Some db changes for sharing
Sharing route added
Other minor changes
This commit is contained in:
Marcos Zuriaga 2016-10-02 01:56:36 +02:00
parent 54e4b9435f
commit 42b73148e6
No known key found for this signature in database
GPG key ID: 7D15585354D072FF
12 changed files with 268 additions and 26 deletions

View file

@ -485,7 +485,7 @@
<field> <field>
<name>item_id</name> <name>item_id</name>
<type>integer</type> <type>integer</type>
<notnull>true</notnull><name>shared_key</name> <notnull>true</notnull>
<type>clob</type> <type>clob</type>
<notnull>true</notnull> <notnull>true</notnull>
<length>8</length> <length>8</length>
@ -514,6 +514,22 @@
<type>clob</type> <type>clob</type>
<notnull>true</notnull> <notnull>true</notnull>
</field> </field>
<field>
<name>permissions</name>
<type>integer</type>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>3</length>
<default>0</default>
</field>
<field>
<name>created</name>
<type>integer</type>
<length>64</length>
<default>0</default>
<notnull>false</notnull>
<unsigned>true</unsigned>
</field>
</declaration> </declaration>
</table> </table>
</database> </database>

View file

@ -5,7 +5,7 @@
<description>A password manager for Nextcloud</description> <description>A password manager for Nextcloud</description>
<licence>AGPL</licence> <licence>AGPL</licence>
<author>Sander Brand</author> <author>Sander Brand</author>
<version>1.0.2.11</version> <version>1.0.2.13</version>
<namespace>Passman</namespace> <namespace>Passman</namespace>
<category>other</category> <category>other</category>
<website>https://github.com/nextcloud/passman/</website> <website>https://github.com/nextcloud/passman/</website>

View file

@ -49,6 +49,7 @@ return [
//Sharing stuff //Sharing stuff
['name' => 'share#search', 'url' => '/api/v2/sharing/search', 'verb' => 'POST'], ['name' => 'share#search', 'url' => '/api/v2/sharing/search', 'verb' => 'POST'],
['name' => 'share#getVaultsByUser', 'url' => '/api/v2/sharing/vaults/{user_id}', 'verb' => 'GET'], ['name' => 'share#getVaultsByUser', 'url' => '/api/v2/sharing/vaults/{user_id}', 'verb' => 'GET'],
['name' => 'share#applyIntermediateShare', 'url' => '/api/v2/sharing/share', 'verb' => 'POST'],
//Internal API //Internal API

View file

@ -12,6 +12,7 @@
namespace OCA\Passman\Controller; namespace OCA\Passman\Controller;
use OCA\Passman\Db\Vault; use OCA\Passman\Db\Vault;
use OCA\Passman\Service\ShareService;
use OCP\IRequest; use OCP\IRequest;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\ApiController; use OCP\AppFramework\ApiController;
@ -32,6 +33,8 @@ class ShareController extends ApiController {
private $groupManager; private $groupManager;
private $userManager; private $userManager;
private $vaultService; private $vaultService;
private $shareService;
private $limit = 50; private $limit = 50;
private $offset = 0; private $offset = 0;
@ -43,7 +46,8 @@ class ShareController extends ApiController {
IGroupManager $groupManager, IGroupManager $groupManager,
IUserManager $userManager, IUserManager $userManager,
ActivityService $activityService, ActivityService $activityService,
VaultService $vaultService VaultService $vaultService,
ShareService $shareService
) { ) {
parent::__construct($AppName, $request); parent::__construct($AppName, $request);
$this->userId = $UserId; $this->userId = $UserId;
@ -51,8 +55,12 @@ class ShareController extends ApiController {
$this->groupManager = $groupManager; $this->groupManager = $groupManager;
$this->activityService = $activityService; $this->activityService = $activityService;
$this->vaultService = $vaultService; $this->vaultService = $vaultService;
$this->shareService = $shareService;
} }
public function applyIntermediateShare($item_id, $item_guid, $vaults, $permissions){
$this->shareService->createBulkRequests($item_id, $item_guid, $vaults, $permissions);
}
public function searchUsers($search) { public function searchUsers($search) {
$users = array(); $users = array();
@ -119,7 +127,7 @@ class ShareController extends ApiController {
foreach($user_vaults as $vault){ foreach($user_vaults as $vault){
array_push($result, array_push($result,
array( array(
'vault_id' => $vault, 'vault_id' => $vault->getId(),
'guid' => $vault->getGuid(), 'guid' => $vault->getGuid(),
'public_sharing_key' => $vault->getPublicSharingKey(), 'public_sharing_key' => $vault->getPublicSharingKey(),
'user_id' => $user_id, 'user_id' => $user_id,

View file

@ -101,9 +101,17 @@ angular.module('passmanApp')
}; };
$scope.shareWith = function(shareWith, selectedAccessLevel){ $scope.shareWith = function(shareWith, selectedAccessLevel){
//@TODO Improve this so we can add, edit and remove users and permissions.
$scope.inputSharedWith = []; $scope.inputSharedWith = [];
if(shareWith.length > 0) { if(shareWith.length > 0) {
shareWithMainLoop:
for (var i = 0; i < shareWith.length; i++) { for (var i = 0; i < shareWith.length; i++) {
// Avoid adding twice the same user.
for (var x = 0; x < $scope.share_settings.credentialSharedWithUserAndGroup.length; x++){
if (shareWith[x].uid == $scope.share_settings.credentialSharedWithUserAndGroup[i].userId){
continue shareWithMainLoop;
}
}
var obj = { var obj = {
userId: shareWith[i].uid, userId: shareWith[i].uid,
displayName: shareWith[i].text, displayName: shareWith[i].text,
@ -140,27 +148,34 @@ angular.module('passmanApp')
console.log(data); console.log(data);
var start = new Date().getTime() / 1000; var start = new Date().getTime() / 1000;
ShareService.cypherRSAStringWithPublicKeyBulkAsync(data, key) ShareService.cypherRSAStringWithPublicKeyBulkAsync(list[iterator].vaults, key)
.progress(function (data) { .progress(function (data) {
$scope.share_settings.cypher_progress.done ++; $scope.share_settings.cypher_progress.done ++;
$scope.share_settings.cypher_progress.percent = $scope.share_settings.cypher_progress.done / $scope.share_settings.cypher_progress.total * 100; $scope.share_settings.cypher_progress.percent = $scope.share_settings.cypher_progress.done / $scope.share_settings.cypher_progress.total * 100;
$scope.$digest(); $scope.$digest();
}) })
.then(function (result) { .then(function (result) {
console.log(result); console.log(result);
console.log("Took: " + ((new Date().getTime() / 1000) - start) + "s to cypher the string for user [" + data[0].user_id + "]"); console.log("Took: " + ((new Date().getTime() / 1000) - start) + "s to cypher the string for user [" + data[0].user_id + "]");
$scope.share_settings.cypher_progress.times.push({ $scope.share_settings.cypher_progress.times.push({
time: ((new Date().getTime() / 1000) - start), time: ((new Date().getTime() / 1000) - start),
user: data[0].user_id user: data[0].user_id
}); });
$scope.$digest(); list[iterator].vaults = result;
}); $scope.uploadChanges(list[iterator]);
$scope.$digest();
});
}); });
} }
} }
}) })
}; };
$scope.uploadChanges = function(user) {
ShareService.shareWithUser(storedCredential, user);
//@TODO Encrypt the credential once all users have the sharing keys.
};
$scope.calculate_total_time = function(){ $scope.calculate_total_time = function(){
$scope.share_settings.cypher_progress.times = $scope.share_settings.cypher_progress.times || []; $scope.share_settings.cypher_progress.times = $scope.share_settings.cypher_progress.times || [];
var total = 0; var total = 0;

View file

@ -25,6 +25,17 @@ angular.module('passmanApp')
} }
}); });
}, },
shareWithUser: function (credential, target_user_data){
var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/share');
return $http.post(queryUrl,
{
item_id: credential.credential_id,
item_guid: credential.guid,
permissions: target_user_data.accessLevel,
vaults: target_user_data.vaults,
}
);
},
getVaultsByUser: function (userId) { getVaultsByUser: function (userId) {
var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/vaults/'+ userId); var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/vaults/'+ userId);
return $http.get(queryUrl, {search: userId}).then(function (response) { return $http.get(queryUrl, {search: userId}).then(function (response) {
@ -105,10 +116,12 @@ angular.module('passmanApp')
cypherRSAStringWithPublicKeyBulkAsync: function(vaults, string){ cypherRSAStringWithPublicKeyBulkAsync: function(vaults, string){
var workload = function(){ var workload = function(){
if (this.current_index < this.vaults.length > 0 && this.vaults.length > 0) { if (this.current_index < this.vaults.length > 0 && this.vaults.length > 0) {
var _vault = angular.copy(this.vaults[this.current_index]);
_vault.key = forge.util.encode64(
_vault.public_sharing_key.encrypt(this.string)
);
this.data.push( this.data.push(
forge.util.encode64( _vault
this.vaults[this.current_index].public_sharing_key.encrypt(this.string)
)
); );
this.current_index++; this.current_index++;

View file

@ -19,6 +19,7 @@ use OCA\Passman\Controller\VaultController;
use OCA\Passman\Service\ActivityService; use OCA\Passman\Service\ActivityService;
use OCA\Passman\Service\CronService; use OCA\Passman\Service\CronService;
use OCA\Passman\Service\CredentialService; use OCA\Passman\Service\CredentialService;
use OCA\Passman\Service\ShareService;
use OCA\Passman\Service\VaultService; use OCA\Passman\Service\VaultService;
use OCA\Passman\Utility\Utils; use OCA\Passman\Utility\Utils;
use OCA\Passman\Service\NotificationService; use OCA\Passman\Service\NotificationService;
@ -52,7 +53,8 @@ class Application extends App {
$server->getGroupManager(), $server->getGroupManager(),
$server->getUserManager(), $server->getUserManager(),
$c->query('ActivityService'), $c->query('ActivityService'),
$c->query('VaultService') $c->query('VaultService'),
$c->query('ShareService')
); );
}); });
@ -87,6 +89,7 @@ class Application extends App {
$container->registerAlias('NotificationService', NotificationService::class); $container->registerAlias('NotificationService', NotificationService::class);
$container->registerAlias('ActivityService', ActivityService::class); $container->registerAlias('ActivityService', ActivityService::class);
$container->registerAlias('VaultService', VaultService::class); $container->registerAlias('VaultService', VaultService::class);
$container->registerAlias('ShareService', ShareService::class);
$container->registerAlias('Utils', Utils::class); $container->registerAlias('Utils', Utils::class);
} }

103
lib/Db/ShareRequest.php Normal file
View file

@ -0,0 +1,103 @@
<?php
/**
* Created by PhpStorm.
* User: wolfi
* Date: 1/10/16
* Time: 23:15
*/
namespace OCA\Passman\Db;
use OCP\AppFramework\Db\Entity;
/**
* @method void setId(integer $value)
* @method integer getId()
* @method void setItemId(integer $value)
* @method integer getItemId()
* @method void setItemGuid(string $value)
* @method string getItemGuid()
* @method void setTargetVaultId(integer $value)
* @method integer getTargetVaultId()
* @method void setTargetVaultGuid(integer $value)
* @method string getTargetVaultGuid()
* @method void setSharedKey(string $value)
* @method string getSharedKey()
* @method void setPermissions(integer $value)
* @method integer getPermissions()
* @method void setCreated(integer $value)
* @method integer getCreated()
*/
class ShareRequest extends Entity implements \JsonSerializable {
CONST READ = 0b00000001;
CONST WRITE = 0b00000010;
CONST OWNER = 0b10000000;
protected
$itemId,
$itemGuid,
$targetVaultId,
$targetVaultGuid,
$sharedKey,
$permissions,
$created;
public function __construct() {
// add types in constructor
$this->addType('itemId', 'integer');
$this->addType('vaultId', 'integer');
$this->addType('permissions', 'integer');
}
/**
* Checks wether a user matches one or more permissions at once
* @param $permission
* @return bool
*/
public function hasPermission($permission) {
$tmp = $this->getPermissions();
$tmp = $tmp & $permission;
return $tmp == $permission;
}
/**
* Adds the given permission or permissions set to the user current permissions
* @param $permission
*/
public function addPermission($permission) {
$tmp = $this->getPermissions();
$tmp = $tmp | $permission;
$this->setPermissions($tmp);
}
/**
* Takes the given permission or permissions out from the user
* @param $permission
*/
public function removePermission($permission) {
$tmp = $this->getPermissions();
$tmp = $tmp & !$permission;
$this->setPermissions($tmp);
}
/**
* Specify data which should be serialized to JSON
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
function jsonSerialize()
{
return [
'req_id' => $this->getId(),
'item_id' => $this->getItemId(),
'item_guid' => $this->getItemGuid(),
'shared_key' => $this->getSharedKey(),
'permissions' => $this->getPermissions(),
'created' => $this->getCreated(),
];
}
}

View file

@ -0,0 +1,27 @@
<?php
/**
* Created by PhpStorm.
* User: wolfi
* Date: 1/10/16
* Time: 23:15
*/
namespace OCA\Passman\Db;
use OCA\Passman\Utility\Utils;
use OCP\AppFramework\Db\Mapper;
use OCP\IDBConnection;
class ShareRequestMapper extends Mapper {
const TABLE_NAME = '`*PREFIX*passman_share_request`';
public function __construct(IDBConnection $db, Utils $utils) {
parent::__construct($db, self::TABLE_NAME);
$this->utils = $utils;
}
public function createRequest(ShareRequest $request){
parent::insert($request);
}
}

View file

@ -5,7 +5,7 @@
* Time: 14:19 * Time: 14:19
*/ */
namespace OCA\passman\lib\Db; namespace OCA\Passman\Db;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;

View file

@ -6,11 +6,11 @@
* Time: 14:20 * Time: 14:20
*/ */
namespace OCA\passman\lib\Db; namespace OCA\Passman\Db;
use OCP\AppFramework\Db\Mapper; use OCP\AppFramework\Db\Mapper;
use OCP\IGroup; use OCP\IDBConnection;
use OCP\IUser; use OCP\IUser;
use OCA\Passman\Utility\Utils; use OCA\Passman\Utility\Utils;

View file

@ -0,0 +1,56 @@
<?php
/**
* Created by PhpStorm.
* User: wolfi
* Date: 1/10/16
* Time: 21:54
*/
namespace OCA\Passman\Service;
use OCA\Passman\Db\ShareRequest;
use OCA\Passman\Db\ShareRequestMapper;
use OCA\Passman\Db\SharingACLMapper;
class ShareService {
private $sharingACL;
private $shareRequest;
public function __construct(SharingACLMapper $sharingACL, ShareRequestMapper $shareRequest) {
$this->sharingACL = $sharingACL;
$this->shareRequest = $shareRequest;
}
/**
* Creates requests for all the items on the request array of objects.
* This array objects must follow this spec:
* {
* vault_id: The id of the target vault
* guid: The guid of the target vault
* key: The shared key cyphered with the target vault RSA public key
* }
* @param $target_item_id string The shared item ID
* @param $target_item_guid string The shared item GUID
* @param $request_array \stdClass[]
* @param $permissions integer Must be created with a bitmask from options on the ShareRequest class
*/
public function createBulkRequests($target_item_id, $target_item_guid, $request_array, $permissions) {
$created = (new \DateTime())->getTimestamp();
foreach ($request_array as $req){
$t = new ShareRequest();
$t->setItemId($target_item_id);
$t->setItemGuid($target_item_guid);
$t->setTargetVaultId($req->vault_id);
$t->setTargetVaultGuid($req->guid);
$t->setSharedKey($req->key);
$t->setPermissions($permissions);
$t->setCreated($created);
var_dump($req);
var_dump($t);
$this->shareRequest->createRequest($t);
}
}
}