Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3386971
D9124.id30919.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D9124.id30919.diff
View Options
diff --git a/keyserver/src/responders/redux-state-responders.js b/keyserver/src/responders/redux-state-responders.js
--- a/keyserver/src/responders/redux-state-responders.js
+++ b/keyserver/src/responders/redux-state-responders.js
@@ -1,27 +1,61 @@
// @flow
-import t, { type TInterface } from 'tcomb';
+import _keyBy from 'lodash/fp/keyBy.js';
+import t from 'tcomb';
+import type { TInterface } from 'tcomb';
+import { baseLegalPolicies } from 'lib/facts/policies.js';
+import { daysToEntriesFromEntryInfos } from 'lib/reducers/entry-reducer.js';
+import { freshMessageStore } from 'lib/reducers/message-reducer.js';
+import { mostRecentlyReadThread } from 'lib/selectors/thread-selectors.js';
+import { mostRecentMessageTimestamp } from 'lib/shared/message-utils.js';
+import {
+ threadHasPermission,
+ threadIsPending,
+ parsePendingThreadID,
+ createPendingThread,
+} from 'lib/shared/thread-utils.js';
import {
entryStoreValidator,
calendarQueryValidator,
} from 'lib/types/entry-types.js';
+import { defaultCalendarFilters } from 'lib/types/filter-types.js';
import { inviteLinksStoreValidator } from 'lib/types/link-types.js';
-import { messageStoreValidator } from 'lib/types/message-types.js';
+import {
+ defaultNumberPerThread,
+ messageStoreValidator,
+} from 'lib/types/message-types.js';
+import { threadPermissions } from 'lib/types/thread-permission-types.js';
+import { threadTypes } from 'lib/types/thread-types-enum.js';
import { threadStoreValidator } from 'lib/types/thread-types.js';
import {
currentUserInfoValidator,
userInfosValidator,
} from 'lib/types/user-types.js';
+import { currentDateInTimeZone } from 'lib/utils/date-utils.js';
+import { promiseAll } from 'lib/utils/promises.js';
import type { URLInfo } from 'lib/utils/url-utils.js';
-import { tShape } from 'lib/utils/validation-utils.js';
+import { tShape, ashoatKeyserverID } from 'lib/utils/validation-utils.js';
import { navInfoValidator } from 'web/types/nav-types.js';
import type {
InitialReduxState,
InitialKeyserverInfo,
} from 'web/types/redux-types.js';
+import { navInfoFromURL } from 'web/url-utils.js';
-import type { Viewer } from '../session/viewer';
+import { fetchEntryInfos } from '../fetchers/entry-fetchers.js';
+import { fetchPrimaryInviteLinks } from '../fetchers/link-fetchers.js';
+import { fetchMessageInfos } from '../fetchers/message-fetchers.js';
+import { hasAnyNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js';
+import { fetchThreadInfos } from '../fetchers/thread-fetchers.js';
+import {
+ fetchCurrentUserInfo,
+ fetchKnownUserInfos,
+ fetchUserInfos,
+} from '../fetchers/user-fetchers.js';
+import { getWebPushConfig } from '../push/providers.js';
+import { setNewSession } from '../session/cookies.js';
+import { Viewer } from '../session/viewer.js';
const initialKeyserverInfoValidator = tShape<InitialKeyserverInfo>({
sessionID: t.maybe(t.String),
@@ -44,12 +78,258 @@
keyserverInfo: initialKeyserverInfoValidator,
});
-/* eslint-disable no-unused-vars */
async function getInitialReduxStateResponder(
viewer: Viewer,
urlInfo: URLInfo,
): Promise<InitialReduxState> {
- return ({}: any);
+ const hasNotAcknowledgedPoliciesPromise = hasAnyNotAcknowledgedPolicies(
+ viewer.id,
+ baseLegalPolicies,
+ );
+
+ const initialNavInfoPromise = (async () => {
+ let backupInfo = {
+ now: currentDateInTimeZone(viewer.timeZone),
+ };
+ // Some user ids in selectedUserList might not exist in the userInfos
+ // (e.g. they were included in the results of the user search endpoint)
+ // Because of that we keep their userInfos inside the navInfo.
+ if (urlInfo.selectedUserList) {
+ const fetchedUserInfos = await fetchUserInfos(urlInfo.selectedUserList);
+ const userInfos = {};
+ for (const userID in fetchedUserInfos) {
+ const userInfo = fetchedUserInfos[userID];
+ if (userInfo.username) {
+ userInfos[userID] = userInfo;
+ }
+ }
+ backupInfo = { userInfos, ...backupInfo };
+ }
+ return navInfoFromURL(urlInfo, backupInfo);
+ })();
+
+ const calendarQueryPromise = (async () => {
+ const initialNavInfo = await initialNavInfoPromise;
+ return {
+ startDate: initialNavInfo.startDate,
+ endDate: initialNavInfo.endDate,
+ filters: defaultCalendarFilters,
+ };
+ })();
+ const messageSelectionCriteria = { joinedThreads: true };
+ const initialTime = Date.now();
+
+ const threadInfoPromise = fetchThreadInfos(viewer);
+ const messageInfoPromise = fetchMessageInfos(
+ viewer,
+ messageSelectionCriteria,
+ defaultNumberPerThread,
+ );
+ const entryInfoPromise = (async () => {
+ const calendarQuery = await calendarQueryPromise;
+ return await fetchEntryInfos(viewer, [calendarQuery]);
+ })();
+ const currentUserInfoPromise = fetchCurrentUserInfo(viewer);
+ const userInfoPromise = fetchKnownUserInfos(viewer);
+
+ const sessionIDPromise = (async () => {
+ const calendarQuery = await calendarQueryPromise;
+ if (viewer.loggedIn) {
+ await setNewSession(viewer, calendarQuery, initialTime);
+ }
+ return viewer.sessionID;
+ })();
+
+ const threadStorePromise = (async () => {
+ const [{ threadInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
+ threadInfoPromise,
+ hasNotAcknowledgedPoliciesPromise,
+ ]);
+ return { threadInfos: hasNotAcknowledgedPolicies ? {} : threadInfos };
+ })();
+ const messageStorePromise = (async () => {
+ const [
+ { threadInfos },
+ { rawMessageInfos, truncationStatuses },
+ hasNotAcknowledgedPolicies,
+ ] = await Promise.all([
+ threadInfoPromise,
+ messageInfoPromise,
+ hasNotAcknowledgedPoliciesPromise,
+ ]);
+ if (hasNotAcknowledgedPolicies) {
+ return {
+ messages: {},
+ threads: {},
+ local: {},
+ currentAsOf: { [ashoatKeyserverID]: 0 },
+ };
+ }
+ const { messageStore: freshStore } = freshMessageStore(
+ rawMessageInfos,
+ truncationStatuses,
+ mostRecentMessageTimestamp(rawMessageInfos, initialTime),
+ threadInfos,
+ );
+ return freshStore;
+ })();
+ const entryStorePromise = (async () => {
+ const [{ rawEntryInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
+ entryInfoPromise,
+ hasNotAcknowledgedPoliciesPromise,
+ ]);
+ if (hasNotAcknowledgedPolicies) {
+ return {
+ entryInfos: {},
+ daysToEntries: {},
+ lastUserInteractionCalendar: 0,
+ };
+ }
+ return {
+ entryInfos: _keyBy('id')(rawEntryInfos),
+ daysToEntries: daysToEntriesFromEntryInfos(rawEntryInfos),
+ lastUserInteractionCalendar: initialTime,
+ };
+ })();
+ const userInfosPromise = (async () => {
+ const [userInfos, hasNotAcknowledgedPolicies] = await Promise.all([
+ userInfoPromise,
+ hasNotAcknowledgedPoliciesPromise,
+ ]);
+ return hasNotAcknowledgedPolicies ? {} : userInfos;
+ })();
+
+ const navInfoPromise = (async () => {
+ const [
+ { threadInfos },
+ messageStore,
+ currentUserInfo,
+ userInfos,
+ finalNavInfo,
+ ] = await Promise.all([
+ threadInfoPromise,
+ messageStorePromise,
+ currentUserInfoPromise,
+ userInfosPromise,
+ initialNavInfoPromise,
+ ]);
+
+ const requestedActiveChatThreadID = finalNavInfo.activeChatThreadID;
+ if (
+ requestedActiveChatThreadID &&
+ !threadIsPending(requestedActiveChatThreadID) &&
+ !threadHasPermission(
+ threadInfos[requestedActiveChatThreadID],
+ threadPermissions.VISIBLE,
+ )
+ ) {
+ finalNavInfo.activeChatThreadID = null;
+ }
+
+ if (!finalNavInfo.activeChatThreadID) {
+ const mostRecentThread = mostRecentlyReadThread(
+ messageStore,
+ threadInfos,
+ );
+ if (mostRecentThread) {
+ finalNavInfo.activeChatThreadID = mostRecentThread;
+ }
+ }
+
+ if (
+ finalNavInfo.activeChatThreadID &&
+ threadIsPending(finalNavInfo.activeChatThreadID) &&
+ finalNavInfo.pendingThread?.id !== finalNavInfo.activeChatThreadID
+ ) {
+ const pendingThreadData = parsePendingThreadID(
+ finalNavInfo.activeChatThreadID,
+ );
+ if (
+ pendingThreadData &&
+ pendingThreadData.threadType !== threadTypes.SIDEBAR &&
+ currentUserInfo.id
+ ) {
+ const members = [...pendingThreadData.memberIDs, currentUserInfo.id]
+ .map(id => {
+ const userInfo = userInfos[id];
+ if (!userInfo || !userInfo.username) {
+ return undefined;
+ }
+ const { username } = userInfo;
+ return { id, username };
+ })
+ .filter(Boolean);
+ const newPendingThread = createPendingThread({
+ viewerID: currentUserInfo.id,
+ threadType: pendingThreadData.threadType,
+ members,
+ });
+ finalNavInfo.activeChatThreadID = newPendingThread.id;
+ finalNavInfo.pendingThread = newPendingThread;
+ }
+ }
+
+ return finalNavInfo;
+ })();
+ const currentAsOfPromise = (async () => {
+ const hasNotAcknowledgedPolicies = await hasNotAcknowledgedPoliciesPromise;
+ return hasNotAcknowledgedPolicies ? 0 : initialTime;
+ })();
+
+ const pushApiPublicKeyPromise = (async () => {
+ const pushConfig = await getWebPushConfig();
+ if (!pushConfig) {
+ if (process.env.NODE_ENV !== 'development') {
+ console.warn('keyserver/secrets/web_push_config.json should exist');
+ }
+ return null;
+ }
+ return pushConfig.publicKey;
+ })();
+
+ const inviteLinksStorePromise = (async () => {
+ const primaryInviteLinks = await fetchPrimaryInviteLinks(viewer);
+ const links = {};
+ for (const link of primaryInviteLinks) {
+ if (link.primary) {
+ links[link.communityID] = {
+ primaryLink: link,
+ };
+ }
+ }
+ return {
+ links,
+ };
+ })();
+
+ const keyserverInfoPromise = (async () => {
+ const { sessionID, updatesCurrentAsOf } = await promiseAll({
+ sessionID: sessionIDPromise,
+ updatesCurrentAsOf: currentAsOfPromise,
+ });
+
+ return {
+ sessionID,
+ updatesCurrentAsOf,
+ };
+ })();
+
+ const initialReduxState: InitialReduxState = await promiseAll({
+ navInfo: navInfoPromise,
+ currentUserInfo: currentUserInfoPromise,
+ entryStore: entryStorePromise,
+ threadStore: threadStorePromise,
+ userInfos: userInfosPromise,
+ actualizedCalendarQuery: calendarQueryPromise,
+ messageStore: messageStorePromise,
+ dataLoaded: viewer.loggedIn,
+ pushApiPublicKey: pushApiPublicKeyPromise,
+ commServicesAccessToken: null,
+ inviteLinksStore: inviteLinksStorePromise,
+ keyserverInfo: keyserverInfoPromise,
+ });
+
+ return initialReduxState;
}
export { getInitialReduxStateResponder };
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 30, 7:03 AM (21 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2600047
Default Alt Text
D9124.id30919.diff (10 KB)
Attached To
Mode
D9124: [keyserver] Implement `getInitialReduxStateResponder`
Attached
Detach File
Event Timeline
Log In to Comment