Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/utils/validation-utils.js
// @flow | // @flow | ||||
import _mapKeys from 'lodash/fp/mapKeys.js'; | import _mapKeys from 'lodash/fp/mapKeys.js'; | ||||
import _mapValues from 'lodash/fp/mapValues.js'; | import _mapValues from 'lodash/fp/mapValues.js'; | ||||
import type { TType, TInterface } from 'tcomb'; | import type { TType, TInterface } from 'tcomb'; | ||||
import type { PolicyType } from 'lib/facts/policies.js'; | import type { PolicyType } from 'lib/facts/policies.js'; | ||||
import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; | import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; | ||||
import { isWebPlatform } from 'lib/types/device-types.js'; | |||||
import { ServerError } from 'lib/utils/errors.js'; | import { ServerError } from 'lib/utils/errors.js'; | ||||
import { | import { | ||||
tCookie, | tCookie, | ||||
tPassword, | tPassword, | ||||
tPlatform, | tPlatform, | ||||
tPlatformDetails, | tPlatformDetails, | ||||
assertWithValidator, | assertWithValidator, | ||||
tID, | |||||
} from 'lib/utils/validation-utils.js'; | } from 'lib/utils/validation-utils.js'; | ||||
import { fetchNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js'; | import { fetchNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js'; | ||||
import { verifyClientSupported } from '../session/version.js'; | import { verifyClientSupported } from '../session/version.js'; | ||||
import type { Viewer } from '../session/viewer.js'; | import type { Viewer } from '../session/viewer.js'; | ||||
async function validateInput<T>( | async function validateInput<T>( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
inputValidator: ?TType<T>, | inputValidator: ?TType<T>, | ||||
input: T, | input: T, | ||||
) { | ) { | ||||
if (!viewer.isSocket) { | if (!viewer.isSocket) { | ||||
await checkClientSupported(viewer, inputValidator, input); | await checkClientSupported(viewer, inputValidator, input); | ||||
} | } | ||||
checkInputValidator(inputValidator, input); | checkInputValidator(inputValidator, input); | ||||
} | } | ||||
const convertToNewIDSchema = false; | |||||
const keyserverPrefixID = '256'; | |||||
function validateOutput<T>( | |||||
viewer: Viewer, | |||||
outputValidator: TType<T>, | |||||
data: T, | |||||
): T { | |||||
if (!outputValidator.is(data)) { | |||||
console.trace( | |||||
'Output validation failed, validator is:', | |||||
outputValidator.displayName, | |||||
); | |||||
return data; | |||||
} | |||||
if ( | |||||
hasMinCodeVersion(viewer.platformDetails, 1000) && | |||||
!isWebPlatform(viewer.platformDetails?.platform) && | |||||
convertToNewIDSchema | |||||
) { | |||||
return convertServerIDsToClientIDs( | |||||
keyserverPrefixID, | |||||
outputValidator, | |||||
data, | |||||
); | |||||
} | |||||
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: T) { | function checkInputValidator<T>(inputValidator: ?TType<T>, input: T) { | ||||
if (!inputValidator || inputValidator.is(input)) { | if (!inputValidator || inputValidator.is(input)) { | ||||
return; | return; | ||||
} | } | ||||
const error = new ServerError('invalid_parameters'); | const error = new ServerError('invalid_parameters'); | ||||
error.sanitizedInput = input ? sanitizeInput(inputValidator, input) : null; | error.sanitizedInput = input ? sanitizeInput(inputValidator, input) : null; | ||||
throw error; | throw error; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | if (notAcknowledgedPolicies.length) { | ||||
throw new ServerError('policies_not_accepted', { | throw new ServerError('policies_not_accepted', { | ||||
notAcknowledgedPolicies, | notAcknowledgedPolicies, | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
export { | export { | ||||
validateInput, | validateInput, | ||||
validateOutput, | |||||
checkInputValidator, | checkInputValidator, | ||||
redactedString, | redactedString, | ||||
sanitizeInput, | sanitizeInput, | ||||
findFirstInputMatchingValidator, | findFirstInputMatchingValidator, | ||||
checkClientSupported, | checkClientSupported, | ||||
convertServerIDsToClientIDs, | |||||
convertClientIDsToServerIDs, | |||||
convertObject, | convertObject, | ||||
policiesValidator, | policiesValidator, | ||||
}; | }; |