Skip to content

Commit

Permalink
Vaults sharing and permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
tegefaulkes authored and Scott committed Oct 26, 2021
1 parent edd4e3f commit 354cc77
Show file tree
Hide file tree
Showing 17 changed files with 2,243 additions and 328 deletions.
22 changes: 12 additions & 10 deletions src/PolykeyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,16 @@ class Polykey {
fs: fs_,
logger: logger_.getChild('NodeManager'),
}));
const notifications_ =
notificationsManager ??
(await NotificationsManager.createNotificationsManager({
acl: acl_,
db: db_,
nodeManager: nodes_,
keyManager: keys_,
logger: logger_.getChild('NotificationsManager'),
fresh,
}));
const vaults_ =
vaultManager ??
(await VaultManager.createVaultManager({
Expand All @@ -293,6 +303,7 @@ class Polykey {
vaultsKey: keys_.vaultKey,
nodeManager: nodes_,
gestaltGraph: gestalts_,
notificationsManager: notifications_,
acl: acl_,
db: db_,
fs: fs_,
Expand All @@ -314,16 +325,6 @@ class Polykey {
nodeManager: nodes_,
logger: logger_.getChild('Discovery'),
}));
const notifications_ =
notificationsManager ??
(await NotificationsManager.createNotificationsManager({
acl: acl_,
db: db_,
nodeManager: nodes_,
keyManager: keys_,
logger: logger_.getChild('NotificationsManager'),
fresh,
}));

const sessionManager = await SessionManager.createSessionManager({
db: db_,
Expand Down Expand Up @@ -471,6 +472,7 @@ class Polykey {
nodeManager: this.nodes,
sigchain: this.sigchain,
notificationsManager: this.notifications,
acl: this.acl,
});

// Registering providers.
Expand Down
63 changes: 38 additions & 25 deletions src/agent/agentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { utils as claimsUtils, errors as claimsErrors } from '../claims';
import { makeVaultId, makeVaultIdPretty } from '../vaults/utils';
import { makeNodeId } from '../nodes/utils';
import { utils as idUtils } from '@matrixai/id';
import { ACL } from '../acl';
import { NodeId } from '@/nodes/types';

/**
* Creates the client service for use with a GRPCServer
Expand All @@ -39,12 +41,15 @@ function createAgentService({
nodeManager,
notificationsManager,
sigchain,
acl,
}: {
keyManager: KeyManager;
vaultManager: VaultManager;
nodeManager: NodeManager;
sigchain: Sigchain;
notificationsManager: NotificationsManager;
acl: ACL;

}): IAgentServer {
const agentService: IAgentServer = {
echo: async (
Expand All @@ -61,21 +66,36 @@ function createAgentService({
const genWritable = grpcUtils.generatorWritable(call);
const request = call.request;
const vaultNameOrId = request.getVaultId();
let vaultId, vaultName;
let vaultName;
let vaultId = await vaultManager.getVaultId(vaultNameOrId as VaultName);
if (!vaultId) {
try {
vaultId = makeVaultId(idUtils.fromString(vaultNameOrId));
vaultName = await vaultManager.getVaultName(vaultId);
} catch (err) {
throw new vaultsErrors.ErrorVaultUndefined;
}
} else {
vaultName = vaultNameOrId;
}
await vaultManager.openVault(vaultId);
const metaIn = call.metadata;
const nodeId = metaIn.get('nodeId').pop()!.toString() as NodeId;
const actionType = metaIn.get('action').pop()!.toString();
const perms = await acl.getNodePerm(nodeId);
if (!perms) {
throw new vaultsErrors.ErrorVaultPermissionDenied;
}
let vaultPerms = perms.vaults[idUtils.toString(vaultId)];
try {
vaultId = makeVaultId(idUtils.fromString(vaultNameOrId));
await vaultManager.openVault(vaultId);
vaultName = await vaultManager.getVaultName(vaultId);
vaultPerms[actionType]
} catch (err) {
if (err instanceof vaultsErrors.ErrorVaultUndefined) {
vaultId = await vaultManager.getVaultId(vaultNameOrId as VaultName);
await vaultManager.openVault(vaultId);
vaultName = vaultNameOrId;
} else {
throw err;
if (err instanceof TypeError) {
// genWritable.stream.emit('error', vaultsErrors.ErrorVaultPermissionDenied);
throw new vaultsErrors.ErrorVaultPermissionDenied;
return;
}
}
// TODO: Check the permissions here
const meta = new grpc.Metadata();
meta.set('vaultName', vaultName);
meta.set('vaultId', makeVaultIdPretty(vaultId));
Expand Down Expand Up @@ -107,22 +127,15 @@ function createAgentService({
const vaultNameOrId = meta.get('vaultNameOrId').pop()!.toString();
if (vaultNameOrId == null)
throw new ErrorGRPC('vault-name not in metadata.');
let vaultId;
try {
vaultId = makeVaultId(vaultNameOrId);
await vaultManager.openVault(vaultId);
} catch (err) {
if (
err instanceof vaultsErrors.ErrorVaultUndefined ||
err instanceof SyntaxError
) {
vaultId = await vaultManager.getVaultId(vaultNameOrId as VaultName);
await vaultManager.openVault(vaultId);
} else {
throw err;
let vaultId = await vaultManager.getVaultId(vaultNameOrId as VaultName);
if (!vaultId) {
try {
vaultId = makeVaultId(vaultNameOrId);
} catch (err) {
throw new vaultsErrors.ErrorVaultUndefined;
}
}
// TODO: Check the permissions here
await vaultManager.openVault(vaultId);
const response = new agentPB.PackChunk();
const [sideBand, progressStream] = await vaultManager.handlePackRequest(
vaultId,
Expand Down
2 changes: 1 addition & 1 deletion src/vaults/VaultInternal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ class VaultInternal {
}

@ready(new vaultsErrors.ErrorVaultDestroyed())
public async applySchema() {}
public async applySchema(vs) {}
}

export default VaultInternal;
93 changes: 57 additions & 36 deletions src/vaults/VaultManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class VaultManager {
nodeManager,
gestaltGraph,
acl,
notificationsManager,
db,
fs,
logger,
Expand All @@ -78,6 +79,7 @@ class VaultManager {
nodeManager: NodeManager;
gestaltGraph: GestaltGraph;
acl: ACL;
notificationsManager: NotificationsManager;
db: DB;
fs?: FileSystem;
logger?: Logger;
Expand Down Expand Up @@ -110,6 +112,7 @@ class VaultManager {
nodeManager,
gestaltGraph,
acl,
notificationsManager,
db,
vaultsKey,
vaultsDbDomain,
Expand All @@ -127,6 +130,7 @@ class VaultManager {
nodeManager,
gestaltGraph,
acl,
notificationsManager,
db,
vaultsKey,
vaultsDbDomain,
Expand All @@ -141,6 +145,7 @@ class VaultManager {
nodeManager: NodeManager;
gestaltGraph: GestaltGraph;
acl: ACL;
notificationsManager: NotificationsManager;
db: DB;
vaultsKey: VaultKey;
vaultsDbDomain: string;
Expand All @@ -155,6 +160,7 @@ class VaultManager {
this.nodeManager = nodeManager;
this.gestaltGraph = gestaltGraph;
this.acl = acl;
this.notificationsManager = notificationsManager;
this.db = db;
this.vaultsDbDomain = vaultsDbDomain;
this.vaultsNamesDbDomain = vaultsNamesDbDomain;
Expand Down Expand Up @@ -319,16 +325,9 @@ class VaultManager {
if (!vaultName) throw new vaultsErrors.ErrorVaultUndefined();
return await this.gestaltGraph._transaction(async () => {
return await this.acl._transaction(async () => {
const gestalt = await this.gestaltGraph.getGestaltByNode(nodeId);
if (gestalt == null) {
throw new gestaltErrors.ErrorGestaltsGraphNodeIdMissing();
}
const nodes = gestalt.nodes;
for (const node in nodes) {
await this.acl.setNodeAction(nodeId, 'scan');
await this.acl.setVaultAction(vaultId, nodes[node].id, 'pull');
await this.acl.setVaultAction(vaultId, nodes[node].id, 'clone');
}
await this.gestaltGraph.setGestaltActionByNode(nodeId, 'scan');
await this.acl.setVaultAction(vaultId, nodeId, 'pull');
await this.acl.setVaultAction(vaultId, nodeId, 'clone');
await this.notificationsManager.sendNotification(nodeId, {
type: 'VaultShare',
vaultId: idUtils.toString(vaultId),
Expand All @@ -342,12 +341,26 @@ class VaultManager {
});
}

@ready(new vaultsErrors.ErrorVaultManagerDestroyed())
public async unshareVault(vaultId: VaultId, nodeId: NodeId): Promise<void> {
const vaultName = await this.getVaultName(vaultId);
if (!vaultName) throw new vaultsErrors.ErrorVaultUndefined();
return await this.gestaltGraph._transaction(async () => {
return await this.acl._transaction(async () => {
await this.gestaltGraph.unsetGestaltActionByNode(nodeId, 'scan');
await this.acl.unsetVaultAction(vaultId, nodeId, 'pull');
await this.acl.unsetVaultAction(vaultId, nodeId, 'clone');
});
});
}

@ready(new vaultsErrors.ErrorVaultManagerDestroyed())
public async cloneVault(
nodeId: NodeId,
vaultNameOrId: VaultId | VaultName,
): Promise<Vault> {
let vaultName, remoteVaultId;
const thisNodeId = this.nodeManager.getNodeId();
const nodeConnection = await this.nodeManager.getConnectionToNode(nodeId);
const client = nodeConnection.getClient();
const vaultId = await this.generateVaultId();
Expand All @@ -373,13 +386,19 @@ class VaultManager {
const infoResponse = {
async *[Symbol.iterator]() {
const request = new agentPB.InfoRequest();
const meta = new grpc.Metadata();
meta.set('nodeId', thisNodeId);
meta.set('action', 'clone');
if (typeof vaultNameOrId === 'string') {
request.setVaultId(vaultNameOrId);
} else {
request.setVaultId(idUtils.toString(vaultNameOrId));
}
const response = client.vaultsGitInfoGet(request);
response.stream.on('metadata', async (meta) => {
const response = client.vaultsGitInfoGet(request, meta);
response.stream.on('error', (err) => {
throw Error();
});
response.stream.on('metadata', (meta) => {
vaultName = meta.get('vaultName').pop()!.toString();
remoteVaultId = makeVaultId(
meta.get('vaultId').pop()!.toString(),
Expand Down Expand Up @@ -477,7 +496,7 @@ class VaultManager {
await this.db.put(this.vaultsNamesDbDomain, idUtils.toBuffer(vaultId), {
name: vaultName,
defaultPullNode: nodeId,
defaultPullVault: idUtils.toBuffer(remoteVaultId),
defaultPullVault: idUtils.toString(remoteVaultId),
});
return vault;
}, [vaultId]);
Expand All @@ -494,30 +513,29 @@ class VaultManager {
}): Promise<Vault> {
let metaChange = 0;
let vaultMeta, remoteVaultId;
const thisNodeId = this.nodeManager.getNodeId();
return await this._transaction(async () => {
if (pullNodeId == null || pullVaultNameOrId == null) {
vaultMeta = await this.db.get<POJO>(
this.vaultsNamesDbDomain,
idUtils.toBuffer(vaultId),
vaultMeta = await this.db.get<POJO>(
this.vaultsNamesDbDomain,
idUtils.toBuffer(vaultId),
);
if (!vaultMeta) throw new vaultsErrors.ErrorVaultUnlinked();
if (pullNodeId == null) {
pullNodeId = vaultMeta.defaultPullNode;
} else {
metaChange = 1;
vaultMeta.defaultPullNode = pullNodeId;
}
if (pullVaultNameOrId == null) {
pullVaultNameOrId = makeVaultId(
idUtils.fromString(vaultMeta.defaultPullVault),
);
if (!vaultMeta) throw new vaultsErrors.ErrorVaultUnlinked();
if (pullNodeId == null) {
pullNodeId = vaultMeta.defaultPullNode;
} else {
metaChange = 1;
vaultMeta.defaultPullNode = pullNodeId;
}
if (pullVaultNameOrId == null) {
pullVaultNameOrId = makeVaultId(
idUtils.fromBuffer(Buffer.from(vaultMeta.defaultPullVault.data)),
);
} else {
metaChange = 1;
if (typeof pullVaultNameOrId === 'string') {
metaChange = 2;
} else {
metaChange = 1;
if (typeof pullVaultNameOrId === 'string') {
metaChange = 2;
} else {
vaultMeta.defaultPullVault = idUtils.toBuffer(pullVaultNameOrId);
}
vaultMeta.defaultPullVault = idUtils.toString(pullVaultNameOrId);
}
}
const nodeConnection = await this.nodeManager.getConnectionToNode(
Expand All @@ -539,12 +557,15 @@ class VaultManager {
const infoResponse = {
async *[Symbol.iterator]() {
const request = new agentPB.InfoRequest();
const meta = new grpc.Metadata();
meta.set('nodeId', thisNodeId);
meta.set('action', 'clone');
if (typeof pullVaultNameOrId === 'string') {
request.setVaultId(pullVaultNameOrId);
} else {
request.setVaultId(idUtils.toString(pullVaultNameOrId!));
}
const response = client.vaultsGitInfoGet(request);
const response = client.vaultsGitInfoGet(request, meta);
response.stream.on('metadata', async (meta) => {
remoteVaultId = makeVaultId(
meta.get('vaultId').pop()!.toString(),
Expand Down Expand Up @@ -626,7 +647,7 @@ class VaultManager {
throw err;
}
if (metaChange !== 0) {
if (metaChange === 2) vaultMeta.defaultPullVault = remoteVaultId;
if (metaChange === 2) vaultMeta.defaultPullVault = idUtils.toString(remoteVaultId);
await this.db.put(
this.vaultsNamesDbDomain,
idUtils.toBuffer(vaultId),
Expand Down
3 changes: 3 additions & 0 deletions src/vaults/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class ErrorVaultCommitUndefined extends ErrorVaults {
exitCode: number = 10;
}

class ErrorVaultPermissionDenied extends ErrorVaults {}

class ErrorSecretUndefined extends ErrorSecrets {}

class ErrorSecretDefined extends ErrorSecrets {}
Expand All @@ -65,6 +67,7 @@ export {
ErrorInvalidVaultId,
ErrorVaultMergeConflict,
ErrorVaultCommitUndefined,
ErrorVaultPermissionDenied,
ErrorSecretUndefined,
ErrorSecretDefined,
ErrorReadingSecret,
Expand Down
Loading

0 comments on commit 354cc77

Please sign in to comment.