Skip to content

Commit

Permalink
Fixing the GRPC toError() bug with ErrorValidation
Browse files Browse the repository at this point in the history
  • Loading branch information
emmacasolin committed Feb 14, 2022
1 parent a54598e commit d05d4e5
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 13 deletions.
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);
});
});

0 comments on commit d05d4e5

Please sign in to comment.