Page MenuHomePhabricator

D7851.diff
No OneTemporary

D7851.diff

diff --git a/keyserver/src/utils/validation-utils.js b/keyserver/src/utils/validation-utils.js
--- a/keyserver/src/utils/validation-utils.js
+++ b/keyserver/src/utils/validation-utils.js
@@ -1,8 +1,6 @@
// @flow
-import _mapKeys from 'lodash/fp/mapKeys.js';
-import _mapValues from 'lodash/fp/mapValues.js';
-import type { TType, TInterface } from 'tcomb';
+import type { TType } from 'tcomb';
import type { PolicyType } from 'lib/facts/policies.js';
import {
@@ -17,16 +15,17 @@
tPlatform,
tPlatformDetails,
assertWithValidator,
- tID,
+ convertToNewIDSchema,
+ keyserverPrefixID,
+ convertClientIDsToServerIDs,
+ convertObject,
+ convertServerIDsToClientIDs,
} from 'lib/utils/validation-utils.js';
import { fetchNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js';
import { verifyClientSupported } from '../session/version.js';
import type { Viewer } from '../session/viewer.js';
-const convertToNewIDSchema = false;
-const keyserverPrefixID = '256';
-
async function validateInput<T>(
viewer: Viewer,
inputValidator: TType<T>,
@@ -42,11 +41,15 @@
!isWebPlatform(viewer.platformDetails?.platform) &&
convertToNewIDSchema
) {
- return convertClientIDsToServerIDs(
- keyserverPrefixID,
- inputValidator,
- convertedInput,
- );
+ try {
+ return convertClientIDsToServerIDs(
+ keyserverPrefixID,
+ inputValidator,
+ convertedInput,
+ );
+ } catch (err) {
+ throw new ServerError(err.message);
+ }
}
return convertedInput;
@@ -80,39 +83,6 @@
return data;
}
-function convertServerIDsToClientIDs<T>(
- serverPrefixID: string,
- outputValidator: TType<T>,
- data: T,
-): T {
- const conversionFunction = id => {
- if (id.indexOf('|') !== -1) {
- console.warn(`Server id '${id}' already has a prefix`);
- return id;
- }
- return `${serverPrefixID}|${id}`;
- };
-
- return convertObject(outputValidator, data, [tID], conversionFunction);
-}
-
-function convertClientIDsToServerIDs<T>(
- serverPrefixID: string,
- outputValidator: TType<T>,
- data: T,
-): T {
- const prefix = serverPrefixID + '|';
- const conversionFunction = id => {
- if (id.startsWith(prefix)) {
- return id.substr(prefix.length);
- }
-
- throw new ServerError('invalid_client_id_prefix');
- };
-
- return convertObject(outputValidator, data, [tID], conversionFunction);
-}
-
function checkInputValidator<T>(inputValidator: TType<T>, input: mixed): T {
if (inputValidator.is(input)) {
return assertWithValidator(input, inputValidator);
@@ -227,87 +197,6 @@
return null;
}
-function convertObject<T, I>(
- validator: TType<I>,
- input: I,
- typesToConvert: $ReadOnlyArray<TType<T>>,
- conversionFunction: T => T,
-): I {
- if (input === null || input === undefined) {
- return input;
- }
-
- // While they should be the same runtime object,
- // `TValidator` is `TType<T>` and `validator` is `TType<I>`.
- // Having them have different types allows us to use `assertWithValidator`
- // to change `input` flow type
- const TValidator = typesToConvert[typesToConvert.indexOf(validator)];
- if (TValidator && TValidator.is(input)) {
- const TInput = assertWithValidator(input, TValidator);
- const converted = conversionFunction(TInput);
- return assertWithValidator(converted, validator);
- }
-
- if (validator.meta.kind === 'maybe' || validator.meta.kind === 'subtype') {
- return convertObject(
- validator.meta.type,
- input,
- typesToConvert,
- conversionFunction,
- );
- }
- if (validator.meta.kind === 'interface' && typeof input === 'object') {
- const recastValidator: TInterface<typeof input> = (validator: any);
- const result = {};
- for (const key in input) {
- const innerValidator = recastValidator.meta.props[key];
- result[key] = convertObject(
- innerValidator,
- input[key],
- typesToConvert,
- conversionFunction,
- );
- }
- return assertWithValidator(result, recastValidator);
- }
- if (validator.meta.kind === 'union') {
- for (const innerValidator of validator.meta.types) {
- if (innerValidator.is(input)) {
- return convertObject(
- innerValidator,
- input,
- typesToConvert,
- conversionFunction,
- );
- }
- }
- return input;
- }
- if (validator.meta.kind === 'list' && Array.isArray(input)) {
- const innerValidator = validator.meta.type;
- return (input.map(value =>
- convertObject(innerValidator, value, typesToConvert, conversionFunction),
- ): any);
- }
- if (validator.meta.kind === 'dict' && typeof input === 'object') {
- const domainValidator = validator.meta.domain;
- const codomainValidator = validator.meta.codomain;
- if (typesToConvert.includes(domainValidator)) {
- input = _mapKeys(key => conversionFunction(key))(input);
- }
- return _mapValues(value =>
- convertObject(
- codomainValidator,
- value,
- typesToConvert,
- conversionFunction,
- ),
- )(input);
- }
-
- return input;
-}
-
async function policiesValidator(
viewer: Viewer,
policies: $ReadOnlyArray<PolicyType>,
@@ -339,8 +228,5 @@
sanitizeInput,
findFirstInputMatchingValidator,
checkClientSupported,
- convertServerIDsToClientIDs,
- convertClientIDsToServerIDs,
- convertObject,
policiesValidator,
};
diff --git a/keyserver/src/utils/validation-utils.test.js b/keyserver/src/utils/validation-utils.test.js
--- a/keyserver/src/utils/validation-utils.test.js
+++ b/keyserver/src/utils/validation-utils.test.js
@@ -2,14 +2,9 @@
import t from 'tcomb';
-import { tPassword, tShape, tID } from 'lib/utils/validation-utils.js';
+import { tPassword, tShape } from 'lib/utils/validation-utils.js';
-import {
- convertServerIDsToClientIDs,
- sanitizeInput,
- redactedString,
- convertClientIDsToServerIDs,
-} from './validation-utils.js';
+import { sanitizeInput, redactedString } from './validation-utils.js';
describe('sanitization', () => {
it('should redact a string', () => {
@@ -77,46 +72,3 @@
expect(sanitizeInput(validator, object)).toStrictEqual(redacted);
});
});
-
-describe('id conversion', () => {
- it('should convert string id', () => {
- const validator = tShape({ id: tID });
- const serverData = { id: '1' };
- const clientData = { id: '0|1' };
-
- expect(
- convertServerIDsToClientIDs('0', validator, serverData),
- ).toStrictEqual(clientData);
- expect(
- convertClientIDsToServerIDs('0', validator, clientData),
- ).toStrictEqual(serverData);
- });
-
- it('should convert a complex type', () => {
- const validator = tShape({ ids: t.dict(tID, t.list(tID)) });
- const serverData = { ids: { '1': ['11', '12'], '2': [], '3': ['13'] } };
- const clientData = {
- ids: { '0|1': ['0|11', '0|12'], '0|2': [], '0|3': ['0|13'] },
- };
-
- expect(
- convertServerIDsToClientIDs('0', validator, serverData),
- ).toStrictEqual(clientData);
- expect(
- convertClientIDsToServerIDs('0', validator, clientData),
- ).toStrictEqual(serverData);
- });
-
- it('should convert a refinement', () => {
- const validator = t.refinement(tID, () => true);
- const serverData = '1';
- const clientData = '0|1';
-
- expect(
- convertServerIDsToClientIDs('0', validator, serverData),
- ).toStrictEqual(clientData);
- expect(
- convertClientIDsToServerIDs('0', validator, clientData),
- ).toStrictEqual(serverData);
- });
-});
diff --git a/lib/utils/validation-utils.js b/lib/utils/validation-utils.js
--- a/lib/utils/validation-utils.js
+++ b/lib/utils/validation-utils.js
@@ -1,6 +1,8 @@
// @flow
import invariant from 'invariant';
+import _mapKeys from 'lodash/fp/mapKeys.js';
+import _mapValues from 'lodash/fp/mapValues.js';
import t from 'tcomb';
import type {
TStructProps,
@@ -101,6 +103,123 @@
return (data: any);
}
+const convertToNewIDSchema = false;
+const keyserverPrefixID = '256';
+
+function convertServerIDsToClientIDs<T>(
+ serverPrefixID: string,
+ outputValidator: TType<T>,
+ data: T,
+): T {
+ const conversionFunction = id => {
+ if (id.indexOf('|') !== -1) {
+ console.warn(`Server id '${id}' already has a prefix`);
+ return id;
+ }
+ return `${serverPrefixID}|${id}`;
+ };
+
+ return convertObject(outputValidator, data, [tID], conversionFunction);
+}
+
+function convertClientIDsToServerIDs<T>(
+ serverPrefixID: string,
+ outputValidator: TType<T>,
+ data: T,
+): T {
+ const prefix = serverPrefixID + '|';
+ const conversionFunction = id => {
+ if (id.startsWith(prefix)) {
+ return id.substr(prefix.length);
+ }
+
+ throw new Error('invalid_client_id_prefix');
+ };
+
+ return convertObject(outputValidator, data, [tID], conversionFunction);
+}
+
+function convertObject<T, I>(
+ validator: TType<I>,
+ input: I,
+ typesToConvert: $ReadOnlyArray<TType<T>>,
+ conversionFunction: T => T,
+): I {
+ if (input === null || input === undefined) {
+ return input;
+ }
+
+ // While they should be the same runtime object,
+ // `TValidator` is `TType<T>` and `validator` is `TType<I>`.
+ // Having them have different types allows us to use `assertWithValidator`
+ // to change `input` flow type
+ const TValidator = typesToConvert[typesToConvert.indexOf(validator)];
+ if (TValidator && TValidator.is(input)) {
+ const TInput = assertWithValidator(input, TValidator);
+ const converted = conversionFunction(TInput);
+ return assertWithValidator(converted, validator);
+ }
+
+ if (validator.meta.kind === 'maybe' || validator.meta.kind === 'subtype') {
+ return convertObject(
+ validator.meta.type,
+ input,
+ typesToConvert,
+ conversionFunction,
+ );
+ }
+ if (validator.meta.kind === 'interface' && typeof input === 'object') {
+ const recastValidator: TInterface<typeof input> = (validator: any);
+ const result = {};
+ for (const key in input) {
+ const innerValidator = recastValidator.meta.props[key];
+ result[key] = convertObject(
+ innerValidator,
+ input[key],
+ typesToConvert,
+ conversionFunction,
+ );
+ }
+ return assertWithValidator(result, recastValidator);
+ }
+ if (validator.meta.kind === 'union') {
+ for (const innerValidator of validator.meta.types) {
+ if (innerValidator.is(input)) {
+ return convertObject(
+ innerValidator,
+ input,
+ typesToConvert,
+ conversionFunction,
+ );
+ }
+ }
+ return input;
+ }
+ if (validator.meta.kind === 'list' && Array.isArray(input)) {
+ const innerValidator = validator.meta.type;
+ return (input.map(value =>
+ convertObject(innerValidator, value, typesToConvert, conversionFunction),
+ ): any);
+ }
+ if (validator.meta.kind === 'dict' && typeof input === 'object') {
+ const domainValidator = validator.meta.domain;
+ const codomainValidator = validator.meta.codomain;
+ if (typesToConvert.includes(domainValidator)) {
+ input = _mapKeys(key => conversionFunction(key))(input);
+ }
+ return _mapValues(value =>
+ convertObject(
+ codomainValidator,
+ value,
+ typesToConvert,
+ conversionFunction,
+ ),
+ )(input);
+ }
+
+ return input;
+}
+
export {
tBool,
tString,
@@ -123,4 +242,9 @@
tMediaMessageVideo,
tMediaMessageMedia,
assertWithValidator,
+ convertToNewIDSchema,
+ keyserverPrefixID,
+ convertClientIDsToServerIDs,
+ convertServerIDsToClientIDs,
+ convertObject,
};
diff --git a/lib/utils/validation-utils.test.js b/lib/utils/validation-utils.test.js
--- a/lib/utils/validation-utils.test.js
+++ b/lib/utils/validation-utils.test.js
@@ -1,9 +1,15 @@
// @flow
+import t from 'tcomb';
+
import {
tMediaMessagePhoto,
tMediaMessageVideo,
tNumEnum,
+ tShape,
+ tID,
+ convertServerIDsToClientIDs,
+ convertClientIDsToServerIDs,
} from './validation-utils.js';
import { threadTypes } from '../types/thread-types-enum.js';
import { values } from '../utils/objects.js';
@@ -140,3 +146,46 @@
});
});
});
+
+describe('id conversion', () => {
+ it('should convert string id', () => {
+ const validator = tShape({ id: tID });
+ const serverData = { id: '1' };
+ const clientData = { id: '0|1' };
+
+ expect(
+ convertServerIDsToClientIDs('0', validator, serverData),
+ ).toStrictEqual(clientData);
+ expect(
+ convertClientIDsToServerIDs('0', validator, clientData),
+ ).toStrictEqual(serverData);
+ });
+
+ it('should convert a complex type', () => {
+ const validator = tShape({ ids: t.dict(tID, t.list(tID)) });
+ const serverData = { ids: { '1': ['11', '12'], '2': [], '3': ['13'] } };
+ const clientData = {
+ ids: { '0|1': ['0|11', '0|12'], '0|2': [], '0|3': ['0|13'] },
+ };
+
+ expect(
+ convertServerIDsToClientIDs('0', validator, serverData),
+ ).toStrictEqual(clientData);
+ expect(
+ convertClientIDsToServerIDs('0', validator, clientData),
+ ).toStrictEqual(serverData);
+ });
+
+ it('should convert a refinement', () => {
+ const validator = t.refinement(tID, () => true);
+ const serverData = '1';
+ const clientData = '0|1';
+
+ expect(
+ convertServerIDsToClientIDs('0', validator, serverData),
+ ).toStrictEqual(clientData);
+ expect(
+ convertClientIDsToServerIDs('0', validator, clientData),
+ ).toStrictEqual(serverData);
+ });
+});

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 12:45 PM (22 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2534948
Default Alt Text
D7851.diff (13 KB)

Event Timeline