Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions src/validation/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,45 @@ import { CustomError } from 'ts-custom-error';
import { ErrorPolykey, sysexits } from '../errors';

/**
* This packages the `ErrorParse` array into the `data` property
* This is to allow encoding to and decoding from GRPC errors
* Generic error containing all parsing errors that occurred during
* execution.
*/
class ErrorValidation extends ErrorPolykey {
public readonly errors: Array<ErrorParse>;
constructor(errors: Array<ErrorParse>) {
description = 'Input data failed validation';
exitCode = sysexits.DATAERR;
public errors: Array<ErrorParse>;
constructor(message, data) {
super(message, data);
if (data.errors != null) {
const errors: Array<ErrorParse> = [];
for (const eData of data.errors) {
const errorParse = new ErrorParse(eData.message);
errorParse.keyPath = eData.keyPath;
errorParse.value = eData.value;
errorParse.context = eData.context;
errors.push(errorParse);
}
this.errors = errors;
}
}

/**
* This packages an `ErrorParse` array into the `data` property
* This is to allow encoding to and decoding from GRPC errors
*/
static createFromErrors(errors: Array<ErrorParse>): ErrorValidation {
const message = errors.map((e) => e.message).join('; ');
const data = {
errors: errors.map((e) => ({
message: e.message,
keyPath: e.keyPath,
value: e.value.valueOf(),
context: e.context,
})),
};
super(message, data);
this.description = 'Input data failed validation';
this.exitCode = sysexits.DATAERR;
this.errors = errors;
const e = new ErrorValidation(message, data);
e.errors = errors;
return e;
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/validation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ async function validate(
data = await parse_([], data, { undefined: data });
} catch (e) {
if (e instanceof validationErrors.ErrorParse) {
throw new validationErrors.ErrorValidation(errors);
throw validationErrors.ErrorValidation.createFromErrors(errors);
} else {
throw e;
}
}
if (errors.length > 0) {
throw new validationErrors.ErrorValidation(errors);
throw validationErrors.ErrorValidation.createFromErrors(errors);
}
return data;
}
Expand Down Expand Up @@ -88,13 +88,13 @@ function validateSync(
data = parse_([], data, { undefined: data });
} catch (e) {
if (e instanceof validationErrors.ErrorParse) {
throw new validationErrors.ErrorValidation(errors);
throw validationErrors.ErrorValidation.createFromErrors(errors);
} else {
throw e;
}
}
if (errors.length > 0) {
throw new validationErrors.ErrorValidation(errors);
throw validationErrors.ErrorValidation.createFromErrors(errors);
}
return data;
}
Expand Down
14 changes: 13 additions & 1 deletion tests/client/service/identitiesAuthenticate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import identitiesAuthenticate from '@/client/service/identitiesAuthenticate';
import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb';
import { utils as nodesUtils } from '@/nodes';
import * as validationErrors from '@/validation/errors';
import TestProvider from '../../identities/TestProvider';

describe('identitiesAuthenticate', () => {
Expand Down Expand Up @@ -87,7 +88,6 @@ describe('identitiesAuthenticate', () => {
test('authenticates identity', async () => {
const request = new identitiesPB.Provider();
request.setProviderId(testToken.providerId);
request.setIdentityId(testToken.identityId);
const response = grpcClient.identitiesAuthenticate(
request,
clientUtils.encodeAuthFromPassword(password),
Expand Down Expand Up @@ -123,4 +123,16 @@ describe('identitiesAuthenticate', () => {
testToken.identityId,
);
});
test('cannot authenticate invalid provider', async () => {
const request = new identitiesPB.Provider();
request.setProviderId('');
await expect(
grpcClient
.identitiesAuthenticate(
request,
clientUtils.encodeAuthFromPassword(password),
)
.next(),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});
28 changes: 28 additions & 0 deletions tests/client/service/identitiesClaim.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import identitiesClaim from '@/client/service/identitiesClaim';
import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb';
import * as claimsUtils from '@/claims/utils';
import * as validationErrors from '@/validation/errors';
import TestProvider from '../../identities/TestProvider';
import * as testUtils from '../../utils';

Expand Down Expand Up @@ -199,4 +200,31 @@ describe('identitiesClaim', () => {
testToken.identityId,
);
});
test('cannot claim invalid identity', async () => {
const request = new identitiesPB.Provider();
request.setIdentityId('');
request.setProviderId(testToken.providerId);
await expect(
grpcClient.identitiesClaim(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
request.setIdentityId(testToken.identityId);
request.setProviderId('');
await expect(
grpcClient.identitiesClaim(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
request.setIdentityId('');
request.setProviderId('');
await expect(
grpcClient.identitiesClaim(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});
34 changes: 34 additions & 0 deletions tests/client/service/nodesAdd.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import nodesAdd from '@/client/service/nodesAdd';
import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb';
import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb';
import { utils as nodesUtils } from '@/nodes';
import * as validationErrors from '@/validation/errors';
import * as testUtils from '../../utils';

describe('nodesAdd', () => {
Expand Down Expand Up @@ -155,4 +156,37 @@ describe('nodesAdd', () => {
expect(result!.host).toBe('127.0.0.1');
expect(result!.port).toBe(11111);
});
test('cannot add invalid node', async () => {
// Invalid host
const addressMessage = new nodesPB.Address();
addressMessage.setHost('');
addressMessage.setPort(11111);
const request = new nodesPB.NodeAddress();
request.setNodeId('vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0');
request.setAddress(addressMessage);
await expect(
grpcClient.nodesAdd(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
// Invalid port
addressMessage.setHost('127.0.0.1');
addressMessage.setPort(111111);
await expect(
grpcClient.nodesAdd(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
// Invalid nodeid
addressMessage.setPort(11111);
request.setNodeId('nodeId');
await expect(
grpcClient.nodesAdd(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});
11 changes: 11 additions & 0 deletions tests/client/service/nodesClaim.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import nodesClaim from '@/client/service/nodesClaim';
import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb';
import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb';
import * as validationErrors from '@/validation/errors';
import * as testUtils from '../../utils';

describe('nodesClaim', () => {
Expand Down Expand Up @@ -212,4 +213,14 @@ describe('nodesClaim', () => {
expect(response).toBeInstanceOf(utilsPB.StatusMessage);
expect(response.getSuccess()).toBeTruthy();
});
test('cannot claim an invalid node', async () => {
const request = new nodesPB.Claim();
request.setNodeId('nodeId');
await expect(
grpcClient.nodesClaim(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});
11 changes: 11 additions & 0 deletions tests/client/service/nodesFind.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '@/client';
import nodesFind from '@/client/service/nodesFind';
import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb';
import * as validationErrors from '@/validation/errors';
import * as testUtils from '../../utils';

describe('nodesFind', () => {
Expand Down Expand Up @@ -153,4 +154,14 @@ describe('nodesFind', () => {
expect(response.getAddress()!.getHost()).toBe('127.0.0.1');
expect(response.getAddress()!.getPort()).toBe(11111);
});
test('cannot find an invalid node', async () => {
const request = new nodesPB.Node();
request.setNodeId('nodeId');
await expect(
grpcClient.nodesFind(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});
11 changes: 11 additions & 0 deletions tests/client/service/nodesPing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import nodesPing from '@/client/service/nodesPing';
import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb';
import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb';
import * as validationErrors from '@/validation/errors';
import * as testUtils from '../../utils';

describe('nodesPing', () => {
Expand Down Expand Up @@ -158,4 +159,14 @@ describe('nodesPing', () => {
expect(response).toBeInstanceOf(utilsPB.StatusMessage);
expect(response.getSuccess()).toBeTruthy();
});
test('cannot ping an invalid node', async () => {
const request = new nodesPB.Node();
request.setNodeId('nodeId');
await expect(
grpcClient.nodesPing(
request,
clientUtils.encodeAuthFromPassword(password),
),
).rejects.toThrow(validationErrors.ErrorValidation);
});
});