diff --git a/keyserver/src/endpoints.js b/keyserver/src/endpoints.js --- a/keyserver/src/endpoints.js +++ b/keyserver/src/endpoints.js @@ -1,6 +1,6 @@ // @flow -import { policyTypes } from 'lib/facts/policies.js'; +import { baseLegalPolicies } from 'lib/facts/policies.js'; import type { Endpoint } from 'lib/types/endpoints'; import { @@ -60,8 +60,6 @@ import { codeVerificationResponder } from './responders/verification-responders'; import { uploadDeletionResponder } from './uploads/uploads'; -const baseLegalPolicies = [policyTypes.tosAndPrivacyPolicy]; - const jsonEndpoints: { [id: Endpoint]: JSONResponder } = { create_account: { responder: accountCreationResponder, diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js --- a/keyserver/src/responders/user-responders.js +++ b/keyserver/src/responders/user-responders.js @@ -5,7 +5,7 @@ import t from 'tcomb'; import bcrypt from 'twin-bcrypt'; -import { policies } from 'lib/facts/policies.js'; +import { baseLegalPolicies, policies } from 'lib/facts/policies.js'; import { hasMinCodeVersion } from 'lib/shared/version-utils'; import type { ResetPasswordRequest, @@ -51,6 +51,7 @@ import { checkAndInvalidateSIWENonceEntry } from '../deleters/siwe-nonce-deleters.js'; import { fetchEntryInfos } from '../fetchers/entry-fetchers'; import { fetchMessageInfos } from '../fetchers/message-fetchers'; +import { fetchNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js'; import { fetchThreadInfos } from '../fetchers/thread-fetchers'; import { fetchKnownUserInfos, @@ -210,6 +211,31 @@ deleteCookie(viewer.cookieID), ]); viewer.setNewCookie(userViewerData); + + const notAcknowledgedPolicies = await fetchNotAcknowledgedPolicies( + viewer, + baseLegalPolicies, + ); + if ( + notAcknowledgedPolicies.length && + hasMinCodeVersion(viewer.platformDetails, 1000) + ) { + const currentUserInfo = await fetchLoggedInUserInfo(viewer); + return { + notAcknowledgedPolicies, + currentUserInfo: currentUserInfo, + rawMessageInfos: [], + truncationStatuses: [], + userInfos: [], + rawEntryInfos: [], + serverTime: 0, + cookieChange: { + threadInfos: {}, + userInfos: [], + }, + }; + } + if (calendarQuery) { await setNewSession(viewer, calendarQuery, newServerTime); } diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js --- a/lib/actions/user-actions.js +++ b/lib/actions/user-actions.js @@ -147,6 +147,7 @@ userInfos, updatesCurrentAsOf: response.serverTime, logInActionSource: logInInfo.logInActionSource, + notAcknowledgedPolicies: response.notAcknowledgedPolicies, }; }; diff --git a/lib/facts/policies.js b/lib/facts/policies.js --- a/lib/facts/policies.js +++ b/lib/facts/policies.js @@ -9,3 +9,5 @@ export const policies: $ReadOnlyArray = values(policyTypes); export type PolicyType = $Values; + +export const baseLegalPolicies = [policyTypes.tosAndPrivacyPolicy]; diff --git a/lib/hooks/log-in-call.js b/lib/hooks/log-in-call.js new file mode 100644 --- /dev/null +++ b/lib/hooks/log-in-call.js @@ -0,0 +1,35 @@ +// @flow + +import * as React from 'react'; +import { useDispatch } from 'react-redux'; + +import { logIn } from '../actions/user-actions.js'; +import type { LogInInfo, LogInResult } from '../types/account-types.js'; +import { forcePolicyAcknowledgmentActionType } from '../types/policy-types.js'; +import { useServerCall } from '../utils/action-utils.js'; + +function useLogInServerCall(): (logInInfo: LogInInfo) => Promise { + const dispatch = useDispatch(); + const callLogIn = useServerCall(logIn); + + return React.useCallback( + async (logInInfo: LogInInfo) => { + const result = await callLogIn(logInInfo); + if ( + result.notAcknowledgedPolicies && + result.notAcknowledgedPolicies.length + ) { + dispatch({ + type: forcePolicyAcknowledgmentActionType, + payload: { + notAcknowledgedPolicies: result.notAcknowledgedPolicies, + }, + }); + } + return result; + }, + [callLogIn, dispatch], + ); +} + +export { useLogInServerCall }; diff --git a/lib/types/account-types.js b/lib/types/account-types.js --- a/lib/types/account-types.js +++ b/lib/types/account-types.js @@ -129,6 +129,7 @@ threadInfos: { +[id: string]: RawThreadInfo }, userInfos: $ReadOnlyArray, }, + notAcknowledgedPolicies?: $ReadOnlyArray, }; export type LogInResult = { @@ -139,6 +140,7 @@ +calendarResult: CalendarResult, +updatesCurrentAsOf: number, +logInActionSource: LogInActionSource, + +notAcknowledgedPolicies?: $ReadOnlyArray, }; export type UpdatePasswordRequest = { diff --git a/native/account/log-in-panel.react.js b/native/account/log-in-panel.react.js --- a/native/account/log-in-panel.react.js +++ b/native/account/log-in-panel.react.js @@ -5,7 +5,8 @@ import { View, StyleSheet, Alert, Keyboard, Platform } from 'react-native'; import Animated from 'react-native-reanimated'; -import { logInActionTypes, logIn } from 'lib/actions/user-actions'; +import { logInActionTypes } from 'lib/actions/user-actions'; +import { useLogInServerCall } from 'lib/hooks/log-in-call'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { validEmailRegex, @@ -20,7 +21,6 @@ } from 'lib/types/account-types'; import type { LoadingStatus } from 'lib/types/loading-types'; import { - useServerCall, useDispatchActionPromise, type DispatchActionPromise, } from 'lib/utils/action-utils'; @@ -366,7 +366,7 @@ ); const dispatchActionPromise = useDispatchActionPromise(); - const callLogIn = useServerCall(logIn); + const callLogIn = useLogInServerCall(); return (