Page MenuHomePhabricator

D9145.id31301.diff
No OneTemporary

D9145.id31301.diff

diff --git a/keyserver/src/responders/website-responders.js b/keyserver/src/responders/website-responders.js
--- a/keyserver/src/responders/website-responders.js
+++ b/keyserver/src/responders/website-responders.js
@@ -4,80 +4,21 @@
import { detect as detectBrowser } from 'detect-browser';
import type { $Response, $Request } from 'express';
import fs from 'fs';
-import _isEqual from 'lodash/fp/isEqual.js';
-import _keyBy from 'lodash/fp/keyBy.js';
import * as React from 'react';
// eslint-disable-next-line import/extensions
import ReactDOMServer from 'react-dom/server';
-import t from 'tcomb';
import { promisify } from 'util';
import { inviteLinkURL } from 'lib/facts/links.js';
-import { baseLegalPolicies } from 'lib/facts/policies.js';
import stores from 'lib/facts/stores.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 { defaultWebEnabledApps } from 'lib/types/enabled-apps.js';
-import { entryStoreValidator } from 'lib/types/entry-types.js';
-import { defaultCalendarFilters } from 'lib/types/filter-types.js';
-import { keyserverStoreValidator } from 'lib/types/keyserver-types.js';
-import { inviteLinksStoreValidator } from 'lib/types/link-types.js';
-import {
- defaultNumberPerThread,
- messageStoreValidator,
-} from 'lib/types/message-types.js';
-import { defaultEnabledReports } from 'lib/types/report-types.js';
-import { defaultConnectionInfo } from 'lib/types/socket-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 { ServerError } from 'lib/utils/errors.js';
-import { promiseAll } from 'lib/utils/promises.js';
-import { defaultNotifPermissionAlertInfo } from 'lib/utils/push-alerts.js';
-import { infoFromURL, urlInfoValidator } from 'lib/utils/url-utils.js';
-import {
- tBool,
- tNumber,
- tShape,
- tString,
- ashoatKeyserverID,
-} from 'lib/utils/validation-utils.js';
import getTitle from 'web/title/getTitle.js';
-import { navInfoValidator } from 'web/types/nav-types.js';
-import { navInfoFromURL } from 'web/url-utils.js';
-
-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';
-import { streamJSON, waitForStream } from '../utils/json-stream.js';
+import { waitForStream } from '../utils/json-stream.js';
import {
getAppURLFactsFromRequestURL,
getCommAppURLFacts,
} from '../utils/urls.js';
-import { validateOutput, validateInput } from '../utils/validation-utils.js';
const { renderToNodeStream } = ReactDOMServer;
@@ -170,347 +111,17 @@
}
}
-const initialReduxStateValidator = tShape({
- navInfo: navInfoValidator,
- deviceID: t.Nil,
- currentUserInfo: currentUserInfoValidator,
- draftStore: t.irreducible('default draftStore', _isEqual({ drafts: {} })),
- entryStore: entryStoreValidator,
- threadStore: threadStoreValidator,
- userStore: tShape({
- userInfos: userInfosValidator,
- inconsistencyReports: t.irreducible(
- 'default inconsistencyReports',
- _isEqual([]),
- ),
- }),
- messageStore: messageStoreValidator,
- loadingStatuses: t.irreducible('default loadingStatuses', _isEqual({})),
- calendarFilters: t.irreducible(
- 'defaultCalendarFilters',
- _isEqual(defaultCalendarFilters),
- ),
- communityPickerStore: t.irreducible(
- 'default communityPickerStore',
- _isEqual({ chat: null, calendar: null }),
- ),
- windowDimensions: t.irreducible(
- 'default windowDimensions',
- _isEqual({ width: 0, height: 0 }),
- ),
- notifPermissionAlertInfo: t.irreducible(
- 'default notifPermissionAlertInfo',
- _isEqual(defaultNotifPermissionAlertInfo),
- ),
- actualizedCalendarQuery: tShape({
- startDate: t.String,
- endDate: t.String,
- filters: t.irreducible('default filters', _isEqual(defaultCalendarFilters)),
- }),
- watchedThreadIDs: t.irreducible('default watchedThreadIDs', _isEqual([])),
- lifecycleState: tString('active'),
- enabledApps: t.irreducible(
- 'defaultWebEnabledApps',
- _isEqual(defaultWebEnabledApps),
- ),
- reportStore: t.irreducible(
- 'default reportStore',
- _isEqual({
- enabledReports: defaultEnabledReports,
- queuedReports: [],
- }),
- ),
- nextLocalID: tNumber(0),
- deviceToken: t.Nil,
- dataLoaded: t.Boolean,
- windowActive: tBool(true),
- userPolicies: t.irreducible('default userPolicies', _isEqual({})),
- cryptoStore: t.irreducible(
- 'default cryptoStore',
- _isEqual({
- primaryIdentityKeys: null,
- notificationIdentityKeys: null,
- }),
- ),
- pushApiPublicKey: t.maybe(t.String),
- _persist: t.Nil,
- commServicesAccessToken: t.Nil,
- inviteLinksStore: inviteLinksStoreValidator,
- keyserverStore: keyserverStoreValidator,
- initialStateLoaded: tBool(false),
-});
-
async function websiteResponder(
viewer: Viewer,
req: $Request,
res: $Response,
): Promise<void> {
- const appURLFacts = getAppURLFactsFromRequestURL(req.originalUrl);
- const { basePath, baseDomain } = appURLFacts;
+ const { basePath } = getAppURLFactsFromRequestURL(req.originalUrl);
const baseURL = basePath.replace(/\/$/, '');
- const urlPrefix = baseDomain + baseURL;
const loadingPromise = getWebpackCompiledRootComponentForSSR();
- const hasNotAcknowledgedPoliciesPromise = hasAnyNotAcknowledgedPolicies(
- viewer.id,
- baseLegalPolicies,
- );
-
- const initialNavInfoPromise = (async () => {
- try {
- let urlInfo = infoFromURL(decodeURI(req.url));
-
- try {
- urlInfo = await validateInput(viewer, urlInfoValidator, urlInfo, true);
- } catch (exc) {
- // We should still be able to handle older links
- if (exc.message !== 'invalid_client_id_prefix') {
- throw exc;
- }
- }
-
- let backupInfo = {
- now: currentDateInTimeZone(viewer.timeZone),
- };
- // Some user ids in selectedUserList might not exist in the userStore
- // (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);
- } catch (e) {
- throw new ServerError(e.message);
- }
- })();
-
- 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 assetInfoPromise = getAssetInfo();
- 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 userStorePromise = (async () => {
- const [userInfos, hasNotAcknowledgedPolicies] = await Promise.all([
- userInfoPromise,
- hasNotAcknowledgedPoliciesPromise,
- ]);
- return {
- userInfos: hasNotAcknowledgedPolicies ? {} : userInfos,
- inconsistencyReports: [],
- };
- })();
-
- const navInfoPromise = (async () => {
- const [
- { threadInfos },
- messageStore,
- currentUserInfo,
- userStore,
- finalNavInfo,
- ] = await Promise.all([
- threadInfoPromise,
- messageStorePromise,
- currentUserInfoPromise,
- userStorePromise,
- 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 { userInfos } = userStore;
- 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 keyserverStorePromise = (async () => {
- const { sessionID, updatesCurrentAsOf } = await promiseAll({
- sessionID: sessionIDPromise,
- updatesCurrentAsOf: currentAsOfPromise,
- });
-
- return {
- keyserverInfos: {
- [ashoatKeyserverID]: {
- cookie: undefined,
- sessionID,
- updatesCurrentAsOf,
- urlPrefix,
- connection: defaultConnectionInfo,
- lastCommunicatedPlatformDetails: null,
- },
- },
- };
- })();
-
const {
jsURL,
fontsURL,
@@ -562,61 +173,9 @@
reactStream.pipe(res, { end: false });
await waitForStream(reactStream);
- res.write(html`
+ res.end(html`
</div>
<script>
- var preloadedState =
- `);
-
- const initialReduxState = await promiseAll({
- navInfo: navInfoPromise,
- deviceID: null,
- currentUserInfo: currentUserInfoPromise,
- draftStore: { drafts: {} },
- entryStore: entryStorePromise,
- threadStore: threadStorePromise,
- userStore: userStorePromise,
- messageStore: messageStorePromise,
- loadingStatuses: {},
- calendarFilters: defaultCalendarFilters,
- communityPickerStore: { chat: null, calendar: null },
- windowDimensions: { width: 0, height: 0 },
- notifPermissionAlertInfo: defaultNotifPermissionAlertInfo,
- actualizedCalendarQuery: calendarQueryPromise,
- watchedThreadIDs: [],
- lifecycleState: 'active',
- enabledApps: defaultWebEnabledApps,
- reportStore: {
- enabledReports: defaultEnabledReports,
- queuedReports: [],
- },
- nextLocalID: 0,
- deviceToken: null,
- dataLoaded: viewer.loggedIn,
- windowActive: true,
- userPolicies: {},
- cryptoStore: {
- primaryIdentityKeys: null,
- notificationIdentityKeys: null,
- },
- pushApiPublicKey: pushApiPublicKeyPromise,
- _persist: null,
- commServicesAccessToken: null,
- inviteLinksStore: inviteLinksStorePromise,
- keyserverStore: keyserverStorePromise,
- initialStateLoaded: false,
- });
- const validatedInitialReduxState = validateOutput(
- viewer.platformDetails,
- initialReduxStateValidator,
- initialReduxState,
- true,
- );
- const jsonStream = streamJSON(res, validatedInitialReduxState);
-
- await waitForStream(jsonStream);
- res.end(html`
- ;
var baseURL = "${baseURL}";
var olmFilename = "${olmFilename}";
var commQueryExecutorFilename = "${commQueryExecutorFilename}";
diff --git a/web/redux/default-state.js b/web/redux/default-state.js
new file mode 100644
--- /dev/null
+++ b/web/redux/default-state.js
@@ -0,0 +1,93 @@
+// @flow
+
+import { defaultEnabledApps } from 'lib/types/enabled-apps.js';
+import { defaultCalendarFilters } from 'lib/types/filter-types.js';
+import { defaultConnectionInfo } from 'lib/types/socket-types.js';
+import { isDev } from 'lib/utils/dev-utils.js';
+import { defaultNotifPermissionAlertInfo } from 'lib/utils/push-alerts.js';
+import { ashoatKeyserverID } from 'lib/utils/validation-utils.js';
+
+import type { AppState } from './redux-setup.js';
+
+const defaultWebState: AppState = Object.freeze({
+ navInfo: {
+ activeChatThreadID: null,
+ startDate: '',
+ endDate: '',
+ tab: 'chat',
+ },
+ currentUserInfo: null,
+ draftStore: { drafts: {} },
+ entryStore: {
+ entryInfos: {},
+ daysToEntries: {},
+ lastUserInteractionCalendar: 0,
+ },
+ threadStore: {
+ threadInfos: {},
+ },
+ userStore: {
+ userInfos: {},
+ inconsistencyReports: [],
+ },
+ messageStore: {
+ messages: {},
+ threads: {},
+ local: {},
+ currentAsOf: { [ashoatKeyserverID]: 0 },
+ },
+ windowActive: true,
+ pushApiPublicKey: null,
+ cryptoStore: {
+ primaryAccount: null,
+ primaryIdentityKeys: null,
+ notificationAccount: null,
+ notificationIdentityKeys: null,
+ },
+ deviceID: null,
+ windowDimensions: { width: window.width, height: window.height },
+ loadingStatuses: {},
+ calendarFilters: defaultCalendarFilters,
+ deviceToken: null,
+ dataLoaded: false,
+ notifPermissionAlertInfo: defaultNotifPermissionAlertInfo,
+ watchedThreadIDs: [],
+ lifecycleState: 'active',
+ enabledApps: defaultEnabledApps,
+ reportStore: {
+ enabledReports: {
+ crashReports: false,
+ inconsistencyReports: false,
+ mediaReports: false,
+ },
+ queuedReports: [],
+ },
+ nextLocalID: 0,
+ _persist: null,
+ userPolicies: {},
+ commServicesAccessToken: null,
+ inviteLinksStore: {
+ links: {},
+ },
+ actualizedCalendarQuery: {
+ startDate: '',
+ endDate: '',
+ filters: defaultCalendarFilters,
+ },
+ communityPickerStore: { chat: null, calendar: null },
+ keyserverStore: {
+ keyserverInfos: {
+ [ashoatKeyserverID]: {
+ updatesCurrentAsOf: 0,
+ urlPrefix: isDev
+ ? 'http://localhost:3000/comm'
+ : 'https://web.comm.app',
+ connection: { ...defaultConnectionInfo },
+ lastCommunicatedPlatformDetails: null,
+ },
+ },
+ },
+ initialStateLoaded: false,
+});
+
+export { defaultWebState };
diff --git a/web/redux/persist.js b/web/redux/persist.js
--- a/web/redux/persist.js
+++ b/web/redux/persist.js
@@ -35,8 +35,6 @@
import { isSQLiteSupported } from '../database/utils/db-utils.js';
import { workerRequestMessageTypes } from '../types/worker-types.js';
-declare var preloadedState: AppState;
-
const migrations = {
[1]: async state => {
const {
@@ -169,9 +167,7 @@
// the transform might change in the future, but we need to treat
// this code like migration code (it shouldn't change).
if (oldStorage?._persist?.version === 4) {
- const { connection, updatesCurrentAsOf, sessionID } =
- preloadedState.keyserverStore.keyserverInfos[ashoatKeyserverID];
-
+ const defaultConnection = defaultConnectionInfo;
return {
...oldStorage,
keyserverStore: {
@@ -180,9 +176,9 @@
...oldStorage.keyserverStore.keyserverInfos,
[ashoatKeyserverID]: {
...oldStorage.keyserverStore.keyserverInfos[ashoatKeyserverID],
- connection,
- updatesCurrentAsOf,
- sessionID,
+ connection: { ...defaultConnection },
+ updatesCurrentAsOf: 0,
+ sessionID: null,
},
},
},
@@ -223,9 +219,8 @@
keyserverInfos[key] = {
...state.keyserverInfos[key],
connection: { ...defaultConnection },
- updatesCurrentAsOf:
- preloadedState.keyserverStore.keyserverInfos[key].updatesCurrentAsOf,
- sessionID: preloadedState.keyserverStore.keyserverInfos[key].sessionID,
+ updatesCurrentAsOf: 0,
+ sessionID: null,
};
}
return {
diff --git a/web/root.js b/web/root.js
--- a/web/root.js
+++ b/web/root.js
@@ -15,6 +15,7 @@
import { SQLiteDataHandler } from './database/sqlite-data-handler.js';
import { localforageConfig } from './database/utils/constants.js';
import ErrorBoundary from './error-boundary.react.js';
+import { defaultWebState } from './redux/default-state.js';
import InitialReduxStateGate from './redux/initial-state-gate.js';
import { persistConfig } from './redux/persist.js';
import { type AppState, type Action, reducer } from './redux/redux-setup.js';
@@ -23,12 +24,10 @@
localforage.config(localforageConfig);
-declare var preloadedState: AppState;
-
const persistedReducer = persistReducer(persistConfig, reducer);
const store: Store<AppState, Action> = createStore(
persistedReducer,
- preloadedState,
+ defaultWebState,
composeWithDevTools({})(applyMiddleware(thunk, reduxLoggerMiddleware)),
);
const persistor = persistStore(store);

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 30, 4:13 AM (21 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2599519
Default Alt Text
D9145.id31301.diff (21 KB)

Event Timeline