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

Commit 59902e2

Browse files
authored
Merge pull request #4703 from withspectrum/2.7.3
2.7.3
2 parents df7281f + c8233dc commit 59902e2

File tree

16 files changed

+80
-35
lines changed

16 files changed

+80
-35
lines changed

api/routes/api/email.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ emailRouter.get('/unsubscribe', (req, res) => {
6161
case 'newThreadCreated':
6262
case 'newMessageInThreads':
6363
case 'newDirectMessage':
64+
case 'newMention':
6465
return unsubscribeUserFromEmailNotification(userId, type).then(() =>
6566
res
6667
.status(200)

athena/queues/mention-notification.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ export default async ({ data }: Job<MentionNotificationJobData>) => {
4646
// in a private channel where the user is not a member. Users can still be
4747
// mentioned in public channels where they are not a member
4848
const thread = await getThreadById(threadId);
49-
5049
// if for some reason no thread was found, or the thread was deleted
5150
// dont send any notification about the mention
5251
if (!thread || thread.deletedAt) return;
52+
debug('got thread');
5353

5454
const { isPrivate: channelIsPrivate } = await getChannelById(
5555
thread.channelId
@@ -74,6 +74,7 @@ export default async ({ data }: Job<MentionNotificationJobData>) => {
7474
) {
7575
return;
7676
}
77+
debug('user is member in community');
7778

7879
// see if a usersThreads record exists. If it does, and notifications are muted, we
7980
// should not send an email. If the record doesn't exist, it means the person being
@@ -120,8 +121,10 @@ export default async ({ data }: Job<MentionNotificationJobData>) => {
120121
]);
121122

122123
// if the user shouldn't get an email, just add an in-app notif
123-
if (!shouldEmail)
124+
if (!shouldEmail) {
125+
debug('recipient doesnt have an email');
124126
return storeUsersNotifications(storedNotification.id, recipient.id);
127+
}
125128

126129
// if the mention was in a message, get the data about the message
127130
const messagePromise = messageId ? await getMessageById(messageId) : null;

athena/queues/private-community-request-approved.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Raven from 'shared/raven';
66
import { getCommunityById } from '../models/community';
77
import { storeNotification } from '../models/notification';
88
import { storeUsersNotifications } from 'shared/db/queries/usersNotifications';
9-
import { getUsers } from 'shared/db/queries/user';
9+
import { getUserById } from 'shared/db/queries/user';
1010
import { fetchPayload } from '../utils/payloads';
1111
import isEmail from 'validator/lib/isEmail';
1212
import { sendPrivateCommunityRequestApprovedEmailQueue } from 'shared/bull/queues';
@@ -41,25 +41,26 @@ export default async (job: Job<PrivateCommunityRequestApprovedJobData>) => {
4141
const updatedNotification = await storeNotification(nextNotificationRecord);
4242

4343
const community = await getCommunityById(communityId);
44-
const recipients = await getUsers([userId]);
45-
const filteredRecipients = recipients.filter(
46-
user => user && isEmail(user.email)
47-
);
48-
const usersNotificationPromises = filteredRecipients.map(recipient =>
49-
storeUsersNotifications(updatedNotification.id, recipient.id)
44+
const recipient = await getUserById(userId);
45+
46+
const canSendEmail = recipient && recipient.email && isEmail(recipient.email);
47+
48+
const notificationPromise = storeUsersNotifications(
49+
updatedNotification.id,
50+
recipient.id
5051
);
5152

52-
const usersEmailPromises = filteredRecipients.map(recipient =>
53+
const emailPromise =
54+
canSendEmail &&
5355
sendPrivateCommunityRequestApprovedEmailQueue.add({
5456
// $FlowIssue
5557
recipient,
5658
community,
57-
})
58-
);
59+
});
5960

6061
return await Promise.all([
61-
...usersEmailPromises, // handle emails separately
62-
...usersNotificationPromises, // update or store usersNotifications in-app
62+
emailPromise, // handle emails separately
63+
notificationPromise, // update or store usersNotifications in-app
6364
]).catch(err => {
6465
console.error('❌ Error in job:\n');
6566
console.error(err);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Spectrum",
3-
"version": "2.6.4",
3+
"version": "2.7.3",
44
"license": "BSD-3-Clause",
55
"devDependencies": {
66
"@babel/preset-flow": "^7.0.0",

scripts/deploy.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@ if (servers.indexOf('hyperion') > -1) {
7575
stdio: 'inherit',
7676
});
7777
console.log('Aliasing to hyperion.workers.spectrum.chat');
78-
exec(now('alias hyperion.workers.spectrum.chat'), {
79-
stdio: 'inherit',
80-
});
78+
exec(
79+
now(`alias hyperion.${flags.prod ? 'workers' : 'alpha'}.spectrum.chat`),
80+
{
81+
stdio: 'inherit',
82+
}
83+
);
8184
console.log('Clearing cache');
8285
exec(
8386
now(

shared/db/db.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ poolMaster.on('queueing', size => {
5959
statsd.gauge('db.query_queue.size', size);
6060
});
6161

62-
poolMaster.on('size', size => {
63-
statsd.gauge('db.connections.count', size);
64-
});
62+
setInterval(() => {
63+
statsd.gauge('db.connections.count', poolMaster.getLength());
64+
}, 5000);
6565

6666
// Exit the process on unhealthy db in test env
6767
if (process.env.TEST_DB) {

shared/imgix/signCommunity.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,19 @@ export const signCommunity = (community: DBCommunity, expires?: number): DBCommu
88

99
return {
1010
...rest,
11-
profilePhoto: signImageUrl(profilePhoto, { w: 256, h: 256, expires }),
12-
coverPhoto: signImageUrl(coverPhoto, { w: 1280, h: 384, expires }),
11+
profilePhoto: signImageUrl(profilePhoto, {
12+
w: 256,
13+
h: 256,
14+
dpr: 2,
15+
auto: 'compress',
16+
expires
17+
}),
18+
coverPhoto: signImageUrl(coverPhoto, {
19+
w: 1280,
20+
h: 384,
21+
dpr: 2,
22+
q: 100,
23+
expires
24+
}),
1325
};
1426
};

shared/imgix/signThread.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @flow
22
import type { DBThread } from 'shared/types';
33
import { signImageUrl } from 'shared/imgix';
4+
const url = require('url');
45

56
const signBody = (body?: string, expires?: number): string => {
67
if (!body) {
@@ -32,7 +33,19 @@ const signBody = (body?: string, expires?: number): string => {
3233
const { src } = returnBody.entityMap[key].data;
3334

3435
// transform the body inline with signed image urls
35-
returnBody.entityMap[key].data.src = signImageUrl(src, { expires });
36+
const imageUrlStoredAsSigned =
37+
src.indexOf('https://spectrum.imgix.net') >= 0;
38+
// if the image was stored in the db as a signed url (eg. after the plaintext update to the thread editor)
39+
// we need to remove all query params from the src, then re-sign in order to avoid duplicate signatures
40+
// or sending down a url with an expired signature
41+
if (imageUrlStoredAsSigned) {
42+
const pathname = url.parse(src).pathname;
43+
// always attempt to use the parsed pathname, but fall back to the original src
44+
const sanitized = decodeURIComponent(pathname || src);
45+
returnBody.entityMap[key].data.src = signImageUrl(sanitized, { expires });
46+
} else {
47+
returnBody.entityMap[key].data.src = signImageUrl(src, { expires });
48+
}
3649
});
3750

3851
return JSON.stringify(returnBody);

shared/imgix/signUser.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ export const signUser = (user: DBUser, expires?: number): DBUser => {
1010
profilePhoto: signImageUrl(profilePhoto, {
1111
w: 256,
1212
h: 256,
13+
dpr: 2,
14+
auto: 'compress',
1315
expires,
1416
}),
1517
coverPhoto: signImageUrl(coverPhoto, {
1618
w: 1280,
1719
h: 384,
20+
dpr: 2,
21+
q: 100,
1822
expires,
1923
}),
2024
};

src/components/loading/style.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,7 @@ export const GridProfile = styled.div`
300300
grid-template-areas: 'cover cover' 'meta content';
301301
grid-column-gap: 32px;
302302
width: 100%;
303-
min-width: 100%;
304-
max-width: 100%;
303+
max-width: 1280px;
305304
height: 100%;
306305
min-height: 100vh;
307306
background-color: ${theme.bg.default};

0 commit comments

Comments
 (0)