Skip to content
This repository was archived by the owner on Oct 11, 2022. It is now read-only.
Merged

2.4.42 #4015

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
0ce887b
Guard DM subscription properly
mxstbr Aug 10, 2018
53aff3b
WIP: Upgrade to Apollo Server v2
mxstbr Aug 28, 2018
2cb02a3
Refactor api/index.js
mxstbr Aug 29, 2018
75d140c
Fix subscriptions ctx.user
mxstbr Aug 29, 2018
7e644a4
Merge branch 'alpha' into apollo-server-v2
mxstbr Sep 28, 2018
02fca23
Make file uploads work again! 🎉
mxstbr Sep 28, 2018
08f6bb9
Remove unused package
mxstbr Sep 28, 2018
68ce84a
Make engine + in memory caching work
mxstbr Sep 28, 2018
1d03bea
Fix flow
mxstbr Sep 28, 2018
0cb181d
Re-enable validation rules
mxstbr Sep 28, 2018
d88866c
Stop loading all thread reactions, use denormalized count
mxstbr Oct 1, 2018
6a6f420
Remove unnecessary loaders
brianlovin Oct 1, 2018
b9a35fe
Migration to add denormalized counts
brianlovin Oct 1, 2018
2507b34
Update seed data
brianlovin Oct 1, 2018
85c5fc5
Add channel membercount denormalization
brianlovin Oct 1, 2018
1aab7c8
Add community membercount denormalization
brianlovin Oct 1, 2018
5a4f580
Resolve gql data from new field instead of queries
brianlovin Oct 1, 2018
f146fdf
Update db types
brianlovin Oct 1, 2018
5adecb7
Remove unused functions and swap to reading off model field
brianlovin Oct 1, 2018
1b8eb33
Handle non-existing thread.reactionCount
mxstbr Oct 1, 2018
d1d60af
Update test snapshots
brianlovin Oct 2, 2018
e463733
Merge branch 'alpha' into denormalize-member-counts
brianlovin Oct 2, 2018
de54da8
Update keygrip to version 1.0.3
depfu[bot] Oct 2, 2018
c2b209c
Return changes from db update functions
brianlovin Oct 2, 2018
420f64b
Dont return stale community data to client after mutation
brianlovin Oct 2, 2018
dfbfb8a
Reduce load on threads table in daily digests
brianlovin Oct 2, 2018
b42af67
Merge branch 'alpha' into stop-loading-all-thread-reactiosn
mxstbr Oct 2, 2018
eac0fca
Report fallback reactionCount missing to Sentry
mxstbr Oct 2, 2018
58cd6cf
Merge pull request #3989 from withspectrum/chronos-perf
mxstbr Oct 2, 2018
4de181c
Merge branch 'alpha' into apollo-server-v2
mxstbr Oct 2, 2018
c15b7f2
Forgot to import Raven
mxstbr Oct 2, 2018
081e06c
Update graphql-cost-analysis API
mxstbr Oct 2, 2018
0bf1614
Remove "✌️Spectrum Team" message from notification emails
rafaelalmeidatk Oct 3, 2018
c71e17e
Delete unneeded docs
brianlovin Oct 3, 2018
cfa9f88
Add banning functionality to client
brianlovin Oct 3, 2018
cf85064
Add banUser graphql mutation
brianlovin Oct 3, 2018
1529b31
Add event types for banning users
brianlovin Oct 3, 2018
ab419c9
Add banUser mutation type to schema
brianlovin Oct 3, 2018
309b9b1
Add banUser mutation resolver
brianlovin Oct 3, 2018
18eb0f4
Add filter to deleted dm threads
brianlovin Oct 3, 2018
1e2f90f
Tweak comment
brianlovin Oct 3, 2018
caa72e1
Add shared function to disable all email notifications for a user
brianlovin Oct 3, 2018
f84f576
Update deleteUser mutation to use shared email disable function
brianlovin Oct 3, 2018
78c242e
Update graphql-tag to version 2.10.0
depfu[bot] Oct 3, 2018
6fe8fac
Merge pull request #3992 from withspectrum/depfu/update/mobile/yarn/g…
mxstbr Oct 3, 2018
2ac24ec
Upgrade apollo-engine to latest
mxstbr Oct 3, 2018
a2df1cd
Merge pull request #3993 from withspectrum/upgrade-engine
mxstbr Oct 3, 2018
b3cfb9e
Update stopword to version 0.1.13
depfu[bot] Oct 3, 2018
7600fbf
Remove unused pkg graphql-subscriptions
mxstbr Oct 3, 2018
08ad3eb
Remove unused optics-agent pkg
mxstbr Oct 3, 2018
9bfe7e3
Upgrade to graphql@0.12 in an effort to fix the validationRules bug
mxstbr Oct 3, 2018
78ed161
Upgrade to graphql@0.13.0
mxstbr Oct 3, 2018
9b1f980
Work around graphql-cost-analysis issue with Apollo Server v2 🎉
mxstbr Oct 3, 2018
b16fccf
Merge branch 'alpha' into apollo-server-v2
mxstbr Oct 3, 2018
a474451
Fix test snapshots of error formatter
mxstbr Oct 3, 2018
bc01ebf
Run unit tests before buliding and running for e2e tests
mxstbr Oct 3, 2018
9417dfb
Run build:desktop after e2e tests
mxstbr Oct 3, 2018
306ade6
Update react-apollo to version 2.2.4
depfu[bot] Oct 3, 2018
2c10092
Merge pull request #3996 from withspectrum/depfu/update/mobile/yarn/r…
mxstbr Oct 3, 2018
045e86e
Migrate and seed db before unit tests in CI
mxstbr Oct 3, 2018
00cfd10
Update string-similarity to version 2.0.0
depfu[bot] Oct 3, 2018
bb10291
Merge pull request #3997 from withspectrum/depfu/update/yarn/string-s…
brianlovin Oct 3, 2018
2dcca3e
Merge pull request #3995 from withspectrum/faster-unit-test-fails
brianlovin Oct 3, 2018
2334189
Merge pull request #3994 from withspectrum/depfu/update/vulcan/yarn/s…
brianlovin Oct 3, 2018
cd1dfa0
Merge pull request #3990 from rafaelalmeidatk/alpha
brianlovin Oct 3, 2018
3b5131c
Merge pull request #3983 from withspectrum/depfu/update/yarn/keygrip-…
brianlovin Oct 3, 2018
2ba645e
Add fallbacks to channel and community member count with sentry repor…
brianlovin Oct 3, 2018
67f3d16
Reorder migrations
brianlovin Oct 3, 2018
2519096
Merge pull request #3974 from withspectrum/stop-loading-all-thread-re…
brianlovin Oct 3, 2018
350bff6
Merge pull request #3855 from withspectrum/apollo-server-v2
brianlovin Oct 3, 2018
23c21aa
Update apollo-link-retry to version 2.2.5
depfu[bot] Oct 4, 2018
b29eb1b
Update apollo-link to version 1.2.3
depfu[bot] Oct 4, 2018
da8f952
Merge pull request #3752 from withspectrum/guard-dm-subscription
brianlovin Oct 4, 2018
51917db
Merge pull request #4000 from withspectrum/depfu/update/yarn/apollo-l…
mxstbr Oct 4, 2018
dbf7f29
Merge pull request #3999 from withspectrum/depfu/update/yarn/apollo-l…
mxstbr Oct 4, 2018
a6cb447
Merge branch 'alpha' into denormalize-member-counts
mxstbr Oct 4, 2018
41c91d0
Merge pull request #3998 from withspectrum/ban-users
mxstbr Oct 4, 2018
07a662c
Update apollo-link-http to version 1.5.5
depfu[bot] Oct 4, 2018
022bda5
Update apollo-link-ws to version 1.0.9
depfu[bot] Oct 4, 2018
e2ee061
Upgrade to React v15.6.0
mxstbr Oct 4, 2018
6e6420e
Don't re-render desktop navbar on inbox thread change
mxstbr Oct 4, 2018
afaf376
Merge pull request #3977 from withspectrum/denormalize-member-counts
mxstbr Oct 4, 2018
0655b7f
Merge pull request #4003 from withspectrum/depfu/update/yarn/apollo-l…
mxstbr Oct 4, 2018
ac82126
Fix getDMThread DB query
mxstbr Oct 4, 2018
c4d74ae
Update react-clipboard.js to version 2.0.1
depfu[bot] Oct 4, 2018
e6195e6
Merge pull request #4004 from withspectrum/depfu/update/yarn/apollo-l…
mxstbr Oct 4, 2018
9596082
Update web-push to version 3.3.3
depfu[bot] Oct 4, 2018
5b64d76
Merge pull request #4010 from withspectrum/depfu/update/yarn/web-push…
brianlovin Oct 4, 2018
9b0212b
Merge pull request #4009 from withspectrum/depfu/update/yarn/react-cl…
brianlovin Oct 4, 2018
0073593
Merge pull request #4008 from withspectrum/fix-dm-thread-query
brianlovin Oct 4, 2018
9002509
Merge pull request #4007 from withspectrum/frontend-perf-tweaks
brianlovin Oct 4, 2018
3b22c54
Merge branch 'alpha' into upgrade-react
brianlovin Oct 4, 2018
8592832
Merge pull request #4006 from withspectrum/upgrade-react
brianlovin Oct 4, 2018
a6c7f62
Update react-hot-loader to version 4.3.11
depfu[bot] Oct 4, 2018
f5cbe61
Merge pull request #4011 from withspectrum/depfu/update/yarn/react-ho…
brianlovin Oct 4, 2018
a993276
Merge branch 'alpha' of github.com:withspectrum/spectrum into 2.4.42
brianlovin Oct 4, 2018
81a5cff
2.4.42
brianlovin Oct 4, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,21 @@ jobs:
at: ~/spectrum
- run: yarn run db:migrate
- run: yarn run db:seed
- run:
name: Run Unit Tests
command: yarn run test:ci
- run: *setup-and-build-web
- run: *build-api
- run: *start-api
- run: *start-web
# Wait for the API and webserver to start
- run: ./node_modules/.bin/wait-on http://localhost:3000 http://localhost:3001
- run:
name: Run Unit Tests
command: yarn run test:ci
name: Run E2E Tests
command: test $CYPRESS_RECORD_KEY && yarn run test:e2e -- --record || yarn run test:e2e
- run:
name: Build desktop apps
command: yarn run build:desktop
- run:
name: Run E2E Tests
command: test $CYPRESS_RECORD_KEY && yarn run test:e2e -- --record || yarn run test:e2e

deploy_alpha:
<<: *js_defaults
Expand Down
1 change: 0 additions & 1 deletion admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"apollo-link-http": "^1.3.2",
"apollo-link-ws": "^1.0.4",
"apollo-upload-client": "6.x",
"apollo-upload-server": "^2.0.4",
"apollo-utilities": "^1.0.4",
"d3-array": "^1.2.0",
"graphql": "^0.12.3",
Expand Down
119 changes: 119 additions & 0 deletions api/apollo-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// @flow
import { ApolloServer } from 'apollo-server-express';
import depthLimit from 'graphql-depth-limit';
import costAnalysis from 'graphql-cost-analysis';
import createLoaders from './loaders';
import createErrorFormatter from './utils/create-graphql-error-formatter';
import schema from './schema';
import { getUser, setUserOnline } from './models/user';
import { getUserIdFromReq } from './utils/session-store';
import UserError from './utils/UserError';
import type { DBUser } from 'shared/types';

// NOTE(@mxstbr): Evil hack to make graphql-cost-analysis work with Apollo Server v2
// @see pa-bru/graphql-cost-analysis#12
// @author @arianon
class ProtectedApolloServer extends ApolloServer {
async createGraphQLServerOptions(
req: express$Request,
res: express$Response
): Promise<*> {
const options = await super.createGraphQLServerOptions(req, res);

return {
...options,
validationRules: [
...options.validationRules,
costAnalysis({
maximumCost: 750,
defaultCost: 1,
variables: req.body.variables,
createError: (max, actual) => {
const err = new UserError(
`GraphQL query exceeds maximum complexity, please remove some nesting or fields and try again. (max: ${max}, actual: ${actual})`
);
return err;
},
}),
],
};
}
}

const server = new ProtectedApolloServer({
schema,
formatError: createErrorFormatter(),
// For subscriptions, this gets passed "connection", for everything else "req" and "res"
context: ({ req, res, connection, ...rest }, ...other) => {
if (connection) {
return {
...(connection.context || {}),
};
}

const loaders = createLoaders();
let currentUser = req.user && !req.user.bannedAt ? req.user : null;

return {
loaders,
updateCookieUserData: (data: DBUser) =>
new Promise((res, rej) =>
req.login(data, err => (err ? rej(err) : res()))
),
user: currentUser,
};
},
subscriptions: {
path: '/websocket',
onOperation: (_: any, params: Object) => {
const errorFormatter = createErrorFormatter();
params.formatError = errorFormatter;
return params;
},
onDisconnect: rawSocket => {
return getUserIdFromReq(rawSocket.upgradeReq)
.then(id => id && setUserOnline(id, false))
.catch(err => {
console.error(err);
});
},
onConnect: (connectionParams, rawSocket) =>
getUserIdFromReq(rawSocket.upgradeReq)
.then(id => (id ? setUserOnline(id, true) : null))
.then(user => {
return {
user: user || null,
loaders: createLoaders({ cache: false }),
};
})
.catch(err => {
console.error(err);
return {
loaders: createLoaders({ cache: false }),
};
}),
},
playground: {
settings: {
'editor.theme': 'light',
},
tabs: [
{
endpoint: 'http://localhost:3001/api',
query: `{
user(username: "mxstbr") {
id
username
}
}`,
},
],
},
maxFileSize: 25 * 1024 * 1024, // 25MB
engine: false,
tracing: true,
cacheControl: true,
validationRules: [depthLimit(10)],
});

export default server;
75 changes: 28 additions & 47 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,51 @@ import toobusy from 'shared/middlewares/toobusy';
import addSecurityMiddleware from 'shared/middlewares/security';
import csrf from 'shared/middlewares/csrf';
import { init as initPassport } from './authentication.js';
import apolloServer from './apollo-server';
import { corsOptions } from 'shared/middlewares/cors';
import errorHandler from 'shared/middlewares/error-handler';
import middlewares from './routes/middlewares';
import authRoutes from './routes/auth';
import apiRoutes from './routes/api';
import type { DBUser } from 'shared/types';
import type { Loader } from './loaders/types';

export type GraphQLContext = {
user: DBUser,
updateCookieUserData: (data: DBUser) => Promise<void>,
loaders: {
[key: string]: Loader,
},
};

const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3001;

// Initialize authentication
initPassport();

// API server
const app = express();

// Trust the now proxy
app.set('trust proxy', true);

// Return the request if the server is too busy
app.use(toobusy);

// Security middleware.
addSecurityMiddleware(app);

if (process.env.NODE_ENV === 'production' && !process.env.FORCE_DEV) {
app.use(csrf);
}

// Send all responses as gzip
// All other middlewares
app.use(compression());

import middlewares from './routes/middlewares';
app.use(middlewares);

import authRoutes from './routes/auth';
// Routes
app.use('/auth', authRoutes);

import apiRoutes from './routes/api';
app.use('/api', apiRoutes);

// $FlowIssue
app.use(
(
err: Error,
req: express$Request,
res: express$Response,
next: express$NextFunction
) => {
if (err) {
console.error(err);
res
.status(500)
.send(
'Oops, something went wrong! Our engineers have been alerted and will fix this asap.'
);
Raven.captureException(err);
} else {
return next();
}
}
);
// GraphQL middleware
apolloServer.applyMiddleware({ app, path: '/api', cors: corsOptions });

// Redirect a request to the root path to the main app
app.use('/', (req: express$Request, res: express$Response) => {
res.redirect(
process.env.NODE_ENV === 'production' && !process.env.FORCE_DEV
Expand All @@ -79,20 +67,12 @@ app.use('/', (req: express$Request, res: express$Response) => {
);
});

import type { Loader } from './loaders/types';
export type GraphQLContext = {
user: DBUser,
updateCookieUserData: (data: DBUser) => Promise<void>,
loaders: {
[key: string]: Loader,
},
};

const server = createServer(app);
// $FlowIssue
app.use(errorHandler);

// Create subscriptions server at /websocket
import createSubscriptionsServer from './routes/create-subscription-server';
const subscriptionsServer = createSubscriptionsServer(server, '/websocket');
// We need to create a separate HTTP server to handle GraphQL subscriptions via websockets
const httpServer = createServer(app);
apolloServer.installSubscriptionHandlers(httpServer);

// Start API wrapped in Apollo Engine
const engine = new ApolloEngine({
Expand All @@ -119,10 +99,11 @@ const engine = new ApolloEngine({

engine.listen({
port: PORT,
httpServer: server,
httpServer: httpServer,
graphqlPaths: ['/api'],
});
debug(`GraphQL server running at http://localhost:${PORT}/api`);

debug(`GraphQL API running at http://localhost:${PORT}/api`);

process.on('unhandledRejection', async err => {
console.error('Unhandled rejection', err);
Expand Down
8 changes: 4 additions & 4 deletions api/loaders/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export const __createChannelThreadCountLoader = createLoader(
'group'
);

export const __createChannelMemberCountLoader = createLoader(
channels => getChannelsMemberCounts(channels),
export const __createChannelPendingMembersLoader = createLoader(
channels => getPendingUsersInChannels(channels),
'group'
);

export const __createChannelPendingMembersLoader = createLoader(
channels => getPendingUsersInChannels(channels),
export const __createChannelMemberCountLoader = createLoader(
channels => getChannelsMemberCounts(channels),
'group'
);

Expand Down
2 changes: 1 addition & 1 deletion api/loaders/community.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import {
getCommunities,
getCommunitiesBySlug,
getCommunitiesMemberCounts,
getCommunitiesChannelCounts,
getCommunitiesOnlineMemberCounts,
getCommunitiesMemberCounts,
} from '../models/community';
import { getCommunitiesSettings } from '../models/communitySettings';
import createLoader from './create-loader';
Expand Down
4 changes: 2 additions & 2 deletions api/loaders/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ import {
import { __createNotificationLoader } from './notification';
import {
__createChannelLoader,
__createChannelMemberCountLoader,
__createChannelThreadCountLoader,
__createChannelMemberCountLoader,
__createChannelPendingMembersLoader,
__createChannelSettingsLoader,
} from './channel';
import {
__createCommunityLoader,
__createCommunityBySlugLoader,
__createCommunityMemberCountLoader,
__createCommunityChannelCountLoader,
__createCommunitySettingsLoader,
__createCommunityMemberCountLoader,
__createCommunityOnlineMemberCountLoader,
} from './community';
import {
Expand Down
2 changes: 1 addition & 1 deletion api/loaders/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

export type Loader = {
load: (key: string | Array<string>) => Promise<any>,
loadMany: (keys: Array<string>) => Promise<any>,
loadMany: (keys: Array<*>) => Promise<any>,
clear: (key: string | Array<string>) => void,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
exports.up = function(r, conn) {
return Promise.all([
r
.table('communities')
.update(
{
memberCount: r
.table('usersCommunities')
.getAll(r.row('id'), { index: 'communityId' })
.filter(row => row('isMember').eq(true))
.count()
.default(1),
},
{
nonAtomic: true,
}
)
.run(conn),
r
.table('channels')
.update(
{
memberCount: r
.table('usersChannels')
.getAll(r.row('id'), { index: 'channelId' })
.filter(row => row('isMember').eq(true))
.count()
.default(1),
},
{
nonAtomic: true,
}
)
.run(conn),
]).catch(err => console.error(err));
};
exports.down = function(r, conn) {
return Promise.all([
r
.table('communities')
.update({
memberCount: r.literal(),
})
.run(conn),
r
.table('channels')
.update({
memberCount: r.literal(),
})
.run(conn),
]);
};
Loading