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

Commit 489e89c

Browse files
authored
Merge pull request #4833 from withspectrum/2.8.3
2.8.3
2 parents 34db6f0 + 0075539 commit 489e89c

File tree

28 files changed

+695
-452
lines changed

28 files changed

+695
-452
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
exports.up = function(r, conn) {
2+
return r
3+
.table('threads')
4+
.indexCreate('communityIdAndWatercooler', [
5+
r.row('communityId'),
6+
r.row('watercooler'),
7+
])
8+
.run(conn);
9+
};
10+
11+
exports.down = function(r, conn) {
12+
return r
13+
.table('threads')
14+
.indexDrop('communityIdAndWatercooler')
15+
.run(conn);
16+
};

api/models/community.js

Lines changed: 75 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ export type EditCommunityInput = {
212212
coverFile: Object,
213213
coverPhoto: string,
214214
communityId: string,
215+
watercoolerId?: boolean,
215216
},
216217
};
217218

@@ -409,179 +410,92 @@ export const createCommunity = ({ input }: CreateCommunityInput, user: DBUser):
409410
};
410411

411412
// prettier-ignore
412-
export const editCommunity = ({ input }: EditCommunityInput, userId: string): Promise<DBCommunity> => {
413-
const { name, slug, description, website, file, coverFile, communityId } = input
414-
let { coverPhoto } = input
415-
413+
export const editCommunity = async ({ input }: EditCommunityInput, userId: string): Promise<DBCommunity> => {
414+
const { name, slug, description, website, watercoolerId, file, coverPhoto, coverFile, communityId } = input
415+
416+
let community = await db.table('communities').get(communityId).run()
417+
418+
// if the input comes in with a coverPhoto of length 0 (empty string), it means
419+
// the user was trying to delete or reset their cover photo from the front end.
420+
// in this case we can just set a new default. Otherwise, just keep their
421+
// original cover photo
422+
let updatedCoverPhoto = community.coverPhoto
423+
if (input.coverPhoto.length === 0) {
424+
({ coverPhoto: updatedCoverPhoto } = getRandomDefaultPhoto())
425+
}
426+
416427
return db
417428
.table('communities')
418429
.get(communityId)
430+
.update({
431+
...community,
432+
name,
433+
slug,
434+
description,
435+
website,
436+
watercoolerId: watercoolerId || community.watercoolerId,
437+
coverPhoto: coverFile
438+
? await uploadImage(coverFile, 'communities', community.id)
439+
: updatedCoverPhoto,
440+
profilePhoto: file
441+
? await uploadImage(file, 'communities', community.id)
442+
: community.profilePhoto,
443+
modifiedAt: new Date()
444+
}, { returnChanges: 'always' })
419445
.run()
420446
.then(result => {
421-
return Object.assign({}, result, {
422-
name,
423-
slug,
424-
description,
425-
website,
426-
modifiedAt: new Date(),
427-
});
428-
})
429-
.then(community => {
430-
searchQueue.add({
431-
id: community.id,
432-
type: 'community',
433-
event: 'edited'
434-
})
435-
436-
// if no file was uploaded, update the community with new string values
437-
if (!file && !coverFile) {
438-
// if the coverPhoto was deleted, reset to default
439-
if (!coverPhoto) {
440-
({ coverPhoto } = getRandomDefaultPhoto())
441-
}
442-
return db
443-
.table('communities')
444-
.get(communityId)
445-
.update({ ...community, coverPhoto }, { returnChanges: 'always' })
446-
.run()
447-
.then(result => {
448-
// if an update happened
449-
if (result.replaced === 1) {
450-
trackQueue.add({
451-
userId,
452-
event: events.COMMUNITY_EDITED,
453-
context: { communityId }
454-
})
455-
return result.changes[0].new_val;
456-
}
457-
458-
// an update was triggered from the client, but no data was changed
459-
if (result.unchanged === 1) {
460-
trackQueue.add({
461-
userId,
462-
event: events.COMMUNITY_EDITED_FAILED,
463-
context: { communityId },
464-
properties: {
465-
reason: 'no changes'
466-
}
467-
})
468-
return result.changes[0].old_val;
469-
}
470-
});
447+
if (result.replaced === 1) {
448+
community = result.changes[0].new_val;
449+
trackQueue.add({
450+
userId,
451+
event: events.COMMUNITY_EDITED,
452+
context: { communityId }
453+
})
471454
}
472455

473-
if (file || coverFile) {
474-
if (file && !coverFile) {
475-
// if the coverPhoto was deleted, reset to default
476-
if (!coverPhoto) {
477-
({ coverPhoto } = getRandomDefaultPhoto())
456+
// an update was triggered from the client, but no data was changed
457+
if (result.unchanged === 1) {
458+
community = result.changes[0].old_val;
459+
trackQueue.add({
460+
userId,
461+
event: events.COMMUNITY_EDITED_FAILED,
462+
context: { communityId },
463+
properties: {
464+
reason: 'no changes'
478465
}
479-
return uploadImage(file, 'communities', community.id).then(
480-
profilePhoto => {
481-
// update the community with the profilePhoto
482-
return (
483-
db
484-
.table('communities')
485-
.get(community.id)
486-
.update(
487-
{
488-
...community,
489-
profilePhoto,
490-
coverPhoto
491-
},
492-
{ returnChanges: 'always' }
493-
)
494-
.run()
495-
// return the resulting community with the profilePhoto set
496-
.then(result => {
497-
// if an update happened
498-
if (result.replaced === 1) {
499-
return result.changes[0].new_val;
500-
}
501-
502-
// an update was triggered from the client, but no data was changed
503-
if (result.unchanged === 1) {
504-
return result.changes[0].old_val;
505-
}
506-
})
507-
);
508-
}
509-
);
510-
} else if (!file && coverFile) {
511-
return uploadImage(coverFile, 'communities', community.id).then(
512-
coverPhoto => {
513-
// update the community with the profilePhoto
514-
return (
515-
db
516-
.table('communities')
517-
.get(community.id)
518-
.update(
519-
{
520-
...community,
521-
coverPhoto,
522-
},
523-
{ returnChanges: 'always' }
524-
)
525-
.run()
526-
// return the resulting community with the profilePhoto set
527-
.then(result => {
528-
// if an update happened
529-
if (result.replaced === 1) {
530-
return result.changes[0].new_val;
531-
}
532-
533-
// an update was triggered from the client, but no data was changed
534-
if (result.unchanged === 1) {
535-
return result.changes[0].old_val;
536-
}
537-
})
538-
);
539-
}
540-
);
541-
} else if (file && coverFile) {
542-
const uploadFile = file => {
543-
return uploadImage(file, 'communities', community.id);
544-
};
545-
546-
const uploadCoverFile = coverFile => {
547-
return uploadImage(coverFile, 'communities', community.id);
548-
};
466+
})
467+
}
549468

550-
return Promise.all([
551-
uploadFile(file),
552-
uploadCoverFile(coverFile),
553-
]).then(([profilePhoto, coverPhoto]) => {
554-
return (
555-
db
556-
.table('communities')
557-
.get(community.id)
558-
.update(
559-
{
560-
...community,
561-
coverPhoto,
562-
profilePhoto,
563-
},
564-
{ returnChanges: 'always' }
565-
)
566-
.run()
567-
// return the resulting community with the profilePhoto set
568-
.then(result => {
569-
// if an update happened
570-
if (result.replaced === 1) {
571-
return result.changes[0].new_val;
572-
}
469+
searchQueue.add({
470+
id: communityId,
471+
type: 'community',
472+
event: 'edited'
473+
})
573474

574-
// an update was triggered from the client, but no data was changed
575-
if (result.unchanged === 1) {
576-
return result.changes[0].old_val;
577-
}
475+
return community
476+
})
477+
};
578478

579-
return null;
580-
})
581-
);
582-
});
583-
}
479+
export const setCommunityWatercoolerId = (
480+
communityId: string,
481+
threadId: ?string
482+
) => {
483+
return db
484+
.table('communities')
485+
.get(communityId)
486+
.update(
487+
{
488+
watercoolerId: threadId,
489+
},
490+
{
491+
returnChanges: true,
584492
}
493+
)
494+
.run()
495+
.then(result => {
496+
if (!Array.isArray(result.changes) || result.changes.length === 0)
497+
return getCommunityById(communityId);
498+
return result.changes[0].new_val;
585499
});
586500
};
587501

api/models/thread.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,19 @@ export const getPublicParticipantThreadsByUser = (evalUser: string, options: Pag
418418
});
419419
};
420420

421+
export const getWatercoolerThread = (
422+
communityId: string
423+
): Promise<?DBThread> => {
424+
return db
425+
.table('threads')
426+
.getAll([communityId, true], { index: 'communityIdAndWatercooler' })
427+
.run()
428+
.then(result => {
429+
if (!Array.isArray(result) || result.length === 0) return null;
430+
return result[0];
431+
});
432+
};
433+
421434
export const publishThread = (
422435
// eslint-disable-next-line
423436
{ filesToUpload, ...thread }: Object,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// @flow
2+
import UserError from '../../utils/UserError';
3+
import {
4+
isAuthedResolver as requireAuth,
5+
canModerateCommunity,
6+
} from '../../utils/permissions';
7+
import { events } from 'shared/analytics';
8+
import { trackQueue } from 'shared/bull/queues';
9+
import { publishThread, getWatercoolerThread } from '../../models/thread';
10+
import { getChannelBySlug } from '../../models/channel';
11+
import { setCommunityWatercoolerId } from '../../models/community';
12+
import type { DBCommunity } from 'shared/types';
13+
import type { GraphQLContext } from '../../';
14+
15+
type Args = {
16+
input: {
17+
id: string,
18+
},
19+
};
20+
21+
export default requireAuth(async (_: any, args: Args, ctx: GraphQLContext) => {
22+
const { id: communityId } = args.input;
23+
const { user, loaders } = ctx;
24+
25+
if (!(await canModerateCommunity(user.id, communityId, loaders))) {
26+
trackQueue.add({
27+
userId: user.id,
28+
event: events.COMMUNITY_WATERCOOLER_DISABLED_FAILED,
29+
context: { communityId },
30+
properties: {
31+
reason: 'no permission',
32+
},
33+
});
34+
35+
return new UserError("You don't have permission to do this.");
36+
}
37+
38+
const community: DBCommunity = await loaders.community.load(communityId);
39+
40+
if (!community.watercoolerId) return community;
41+
42+
return setCommunityWatercoolerId(community.id, null);
43+
});

0 commit comments

Comments
 (0)