diff --git a/keyserver/src/responders/handlers.js b/keyserver/src/responders/handlers.js --- a/keyserver/src/responders/handlers.js +++ b/keyserver/src/responders/handlers.js @@ -15,6 +15,7 @@ } from '../session/cookies'; import type { Viewer } from '../session/viewer'; import { type AppURLFacts, getAppURLFactsFromRequestURL } from '../utils/urls'; +import { policiesValidator } from '../utils/validation-utils.js'; import { getMessageForException } from './utils'; export type JSONResponder = { @@ -42,6 +43,7 @@ } const { input } = req.body; viewer = await fetchViewerForJSONRequest(req); + await policiesValidator(viewer, responder.requiredPolicies); const responderResult = await responder.responder(viewer, input); if (res.headersSent) { return; diff --git a/keyserver/src/socket/socket.js b/keyserver/src/socket/socket.js --- a/keyserver/src/socket/socket.js +++ b/keyserver/src/socket/socket.js @@ -75,6 +75,7 @@ import { checkInputValidator, checkClientSupported, + policiesValidator, } from '../utils/validation-utils'; import { RedisSubscriber } from './redis'; import { @@ -628,6 +629,7 @@ const { viewer } = this; invariant(viewer, 'should be set'); const responder = jsonEndpoints[message.payload.endpoint]; + await policiesValidator(viewer, responder.requiredPolicies); const response = await responder.responder(viewer, message.payload.input); return [ { 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,5 +1,7 @@ // @flow +import type { PolicyType } from 'lib/facts/policies.js'; +import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; import { ServerError } from 'lib/utils/errors'; import { tCookie, @@ -8,6 +10,7 @@ tPlatformDetails, } from 'lib/utils/validation-utils'; +import { fetchPolicyAcknowledgments } from '../fetchers/policy-acknowledgment-fetchers.js'; import { verifyClientSupported } from '../session/version'; import type { Viewer } from '../session/viewer'; @@ -153,4 +156,38 @@ return null; } -export { validateInput, checkInputValidator, checkClientSupported }; +async function policiesValidator( + viewer: Viewer, + policies: $ReadOnlyArray, +) { + if (!policies.length) { + return; + } + if (!hasMinCodeVersion(viewer.platformDetails, 1000)) { + return; + } + + const viewerAcknowledgments = await fetchPolicyAcknowledgments( + viewer, + policies, + ); + const notAcknowledgedPolicies = policies.filter(policy => { + const policyAcknowledgment = viewerAcknowledgments.find( + viewerAcknowledgment => viewerAcknowledgment.policy === policy, + ); + return !policyAcknowledgment?.confirmed; + }); + + if (notAcknowledgedPolicies.length) { + throw new ServerError('policies_not_accepted', { + notAcknowledgedPolicies, + }); + } +} + +export { + validateInput, + checkInputValidator, + checkClientSupported, + policiesValidator, +};