From 3b2a9e5c7501ea575c6f0b3c73b7f6fdd728c6aa Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 15 Mar 2018 15:03:01 -0600 Subject: [PATCH 1/6] improved context perf --- graph/context.js | 36 ++++++++++++++++++++++++++++++++---- services/logging.js | 20 ++++++++++---------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/graph/context.js b/graph/context.js index 52bb7fdfc..dcbbc5f6b 100644 --- a/graph/context.js +++ b/graph/context.js @@ -42,6 +42,32 @@ const decorateContextPlugins = (context, contextPlugins) => { ); }; +/** + * Some pieces of the Context are quite complex to setup, using multiple merges + * and other lodash functions. This proxies that access such that it is only + * loaded if it is used. Helpful for a query that only uses a loader, and not a + * mutator. + * + * @param {Object} ctx the graph proxy + * @param {Function} loader the loadable component that should be proxied + */ +const proxyContextLoader = (ctx, loader) => + new Proxy( + { loaded: false, data: null }, + { + get: (obj, prop) => { + if (obj.loaded) { + return obj.data[prop]; + } + + obj.data = loader(ctx); + obj.loaded = true; + + return obj.data[prop]; + }, + } + ); + /** * Stores the request context. */ @@ -61,16 +87,18 @@ class Context { this.connectors = connectors; // Create the loaders. - this.loaders = loaders(this); + this.loaders = proxyContextLoader(this, loaders); // Create the mutators. - this.mutators = mutators(this); + this.mutators = proxyContextLoader(this, mutators); // Decorate the plugin context. - this.plugins = decorateContextPlugins(this, contextPlugins); + this.plugins = proxyContextLoader(this, () => + decorateContextPlugins(this, contextPlugins) + ); // Bind the publish/subscribe to the context. - this.pubsub = getBroker(); + this.pubsub = proxyContextLoader(this, () => getBroker()); // Bind the parent context. this.parent = ctx; diff --git a/services/logging.js b/services/logging.js index 00e9c523b..47ef93af8 100644 --- a/services/logging.js +++ b/services/logging.js @@ -1,18 +1,18 @@ const { version } = require('../package.json'); const Logger = require('bunyan'); const { LOGGING_LEVEL, REVISION_HASH } = require('../config'); +const logger = new Logger({ + src: true, + name: 'talk', + version, + revision: REVISION_HASH, + level: LOGGING_LEVEL, + serializers: Logger.stdSerializers, +}); // Create the logging instance that all logger's are branched from. function createLogger(name, traceID) { - return new Logger({ - src: true, - name, - traceID, - version, - revision: REVISION_HASH, - level: LOGGING_LEVEL, - serializers: Logger.stdSerializers, - }); + return logger.child({ origin: name, traceID }); } -module.exports = { createLogger }; +module.exports = { logger, createLogger }; From db1934e897c417825ffbcf171e60c0e1f8071b8b Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 20 Mar 2018 16:04:41 -0600 Subject: [PATCH 2/6] fixed password reset email form --- routes/api/v1/account.js | 2 +- yarn.lock | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/routes/api/v1/account.js b/routes/api/v1/account.js index e1395323d..f7d8ea126 100644 --- a/routes/api/v1/account.js +++ b/routes/api/v1/account.js @@ -80,7 +80,7 @@ router.post('/password/reset', async (req, res, next) => { token, }, subject: 'Password Reset', - to: email, + email, }); } diff --git a/yarn.lock b/yarn.lock index 3556a26ba..786086d39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8239,10 +8239,6 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pell@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pell/-/pell-1.0.1.tgz#8f1e97165001024e5f371e0ce0b329457c847b5d" - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" From 3415163cfb1cea003b419fe9c19ea3f76c9fd4b4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 20 Mar 2018 16:07:42 -0600 Subject: [PATCH 3/6] changed name based on review --- graph/context.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/graph/context.js b/graph/context.js index dcbbc5f6b..e9ac7ea61 100644 --- a/graph/context.js +++ b/graph/context.js @@ -51,7 +51,7 @@ const decorateContextPlugins = (context, contextPlugins) => { * @param {Object} ctx the graph proxy * @param {Function} loader the loadable component that should be proxied */ -const proxyContextLoader = (ctx, loader) => +const createLazyContextLoader = (ctx, loader) => new Proxy( { loaded: false, data: null }, { @@ -87,18 +87,18 @@ class Context { this.connectors = connectors; // Create the loaders. - this.loaders = proxyContextLoader(this, loaders); + this.loaders = createLazyContextLoader(this, loaders); // Create the mutators. - this.mutators = proxyContextLoader(this, mutators); + this.mutators = createLazyContextLoader(this, mutators); // Decorate the plugin context. - this.plugins = proxyContextLoader(this, () => + this.plugins = createLazyContextLoader(this, () => decorateContextPlugins(this, contextPlugins) ); // Bind the publish/subscribe to the context. - this.pubsub = proxyContextLoader(this, () => getBroker()); + this.pubsub = createLazyContextLoader(this, () => getBroker()); // Bind the parent context. this.parent = ctx; From b43b67e8fa2b828e333a13799aeebf0dd56e830e Mon Sep 17 00:00:00 2001 From: Juan Pablo Kutianski Date: Tue, 20 Mar 2018 23:10:30 -0300 Subject: [PATCH 4/6] change Facebook to Google+ --- plugins/talk-plugin-google-auth/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/talk-plugin-google-auth/README.md b/plugins/talk-plugin-google-auth/README.md index edf0b9488..f68b56c32 100644 --- a/plugins/talk-plugin-google-auth/README.md +++ b/plugins/talk-plugin-google-auth/README.md @@ -11,7 +11,7 @@ plugin: - Client --- -Enables sign-in via Facebook via the server side passport middleware. +Enables sign-in via Google+ via the server side passport middleware. You will need to enable the Google+ API in the dashboard and create credentials for a new OAuth client ID web application. The authorized JavaScript origin @@ -26,4 +26,4 @@ Configuration: the [Google API Console](https://console.developers.google.com/apis/). - `TALK_GOOGLE_CLIENT_SECRET` (**required**) - The Google OAuth2 client ID for your Google login web app. You can learn more about getting a Google Client - ID at the [Google API Console](https://console.developers.google.com/apis/). \ No newline at end of file + ID at the [Google API Console](https://console.developers.google.com/apis/). From a43c173a125423557f93ee51a1891b7ea4d7700a Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 21 Mar 2018 11:04:41 -0600 Subject: [PATCH 5/6] Added support for forcing the notification settings pane --- middleware/staticTemplate.js | 27 ++++++++++++++----- plugin-api/beta/client/selectors/index.js | 1 + .../client/containers/Settings.js | 20 ++++++++++++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/middleware/staticTemplate.js b/middleware/staticTemplate.js index b7d01feb4..01503cca0 100644 --- a/middleware/staticTemplate.js +++ b/middleware/staticTemplate.js @@ -13,6 +13,25 @@ const { const { RECAPTCHA_PUBLIC, WEBSOCKET_LIVE_URI } = require('../config'); +// Grab TALK_CLIENT_* environment variables. +const TALK_CLIENT = /^TALK_CLIENT_/i; + +// TALK_CLIENT_ENV is all the environment keys that are loaded at runtime. +const TALK_CLIENT_ENV = Object.keys(process.env) + .filter(key => TALK_CLIENT.test(key)) + .reduce( + (env, key) => { + env[key] = process.env[key]; + return env; + }, + { + TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, + LIVE_URI: WEBSOCKET_LIVE_URI, + STATIC_URL, + STATIC_ORIGIN, + } + ); + // TEMPLATE_LOCALS stores the static data that is provided as a `text/json` on // to the client from the template. const TEMPLATE_LOCALS = { @@ -20,12 +39,8 @@ const TEMPLATE_LOCALS = { BASE_PATH, MOUNT_PATH, STATIC_URL, - data: { - TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, - LIVE_URI: WEBSOCKET_LIVE_URI, - STATIC_URL, - STATIC_ORIGIN, - }, + TALK_CLIENT_ENV, + data: TALK_CLIENT_ENV, }; // attachStaticLocals will attach the locals to the response only. diff --git a/plugin-api/beta/client/selectors/index.js b/plugin-api/beta/client/selectors/index.js index c3a0b6821..605711dbc 100644 --- a/plugin-api/beta/client/selectors/index.js +++ b/plugin-api/beta/client/selectors/index.js @@ -1 +1,2 @@ export const pluginsConfigSelector = state => state.config.plugins_config; +export const staticConfigSelector = state => state.config.static; diff --git a/plugins/talk-plugin-notifications/client/containers/Settings.js b/plugins/talk-plugin-notifications/client/containers/Settings.js index 27af031e8..5862650ec 100644 --- a/plugins/talk-plugin-notifications/client/containers/Settings.js +++ b/plugins/talk-plugin-notifications/client/containers/Settings.js @@ -9,6 +9,8 @@ import { } from 'plugin-api/beta/client/hocs'; import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils'; import { withUpdateNotificationSettings } from '../mutations'; +import { connect } from 'plugin-api/beta/client/hocs'; +import { staticConfigSelector } from 'plugin-api/beta/client/selectors'; const slots = ['notificationSettings']; @@ -42,8 +44,11 @@ class SettingsContainer extends React.Component { }; getNeedEmailVerification() { - return !this.props.root.me.profiles.some( - profile => profile.provider === 'local' && profile.confirmedAt + return ( + this.props.root.settings.notificationsRequireConfirmation && + !this.props.root.me.profiles.some( + profile => profile.provider === 'local' && profile.confirmedAt + ) ); } @@ -94,11 +99,22 @@ const enhance = compose( } } } + settings { + notificationsRequireConfirmation + } } `, }), + // Grab the static configuration from the redux store. + connect(state => ({ + static: staticConfigSelector(state), + })), excludeIf( props => + // If the environment variable for TALK_CLIENT_FORCE_NOTIFICATION_SETTINGS + // is `TRUE`, then always show it. + props.static.TALK_CLIENT_FORCE_NOTIFICATION_SETTINGS !== 'TRUE' && + // Only show the settings pane if we have a local profile otherwise. !props.root.me.profiles.some(profile => profile.provider === 'local') ), withUpdateNotificationSettings, From 0b017002358097fbce19f92b9e747d9a399500e4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 21 Mar 2018 11:12:04 -0600 Subject: [PATCH 6/6] updated docs --- plugins/talk-plugin-notifications/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/talk-plugin-notifications/README.md b/plugins/talk-plugin-notifications/README.md index 0ce1b61a8..9e8318a0f 100644 --- a/plugins/talk-plugin-notifications/README.md +++ b/plugins/talk-plugin-notifications/README.md @@ -16,6 +16,7 @@ anything. You need to enable one of the `talk-plugin-notifications-category-*` p Configuration: - `DISABLE_REQUIRE_EMAIL_VERIFICATIONS` - When `TRUE`, it will disable the verification email check before sending notifications for those emails. **Note that organizations implementing a custom authentication system _must_ disable this feature, as they don't use our integrated auth**. (Default `FALSE`). +- `TALK_CLIENT_FORCE_NOTIFICATION_SETTINGS` - When `TRUE`, the settings pane for notifications will show always, even if the user does not have a `local` profile. (Default `FALSE`). You can enable other notification options by adding more `talk-plugin-notification-*` plugins! \ No newline at end of file