Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multi squad moderation #2617

Merged
merged 13 commits into from
Feb 6, 2025
4 changes: 2 additions & 2 deletions __tests__/notifications/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ describe('storeNotificationBundle', () => {
);
expect(actual.notification.description).toBeFalsy();
expect(actual.notification.targetUrl).toEqual(
'http://localhost:5002/squads/a/moderate',
'http://localhost:5002/squads/moderate',
);
expect(actual.avatars).toEqual([
{
Expand Down Expand Up @@ -1352,7 +1352,7 @@ describe('storeNotificationBundle', () => {
);
expect(actual.notification.description).toEqual('Lacks value.');
expect(actual.notification.targetUrl).toEqual(
'http://localhost:5002/squads/a/moderate',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we add a redirect on frontend for this since some old notifications might be wrong?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we might have to add it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AmarTrebinjac just a reminder if you did not add it already 🙏 if yes ignore

'http://localhost:5002/squads/moderate?handle=a',
);
expect(actual.avatars).toEqual([
{
Expand Down
99 changes: 76 additions & 23 deletions __tests__/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,33 @@ beforeEach(async () => {
name: 'Joanna Deer',
},
]);
await con.getRepository(SquadSource).save({
id: 'm',
name: 'Moderated Squad',
image: 'http//image.com/m',
handle: 'moderatedSquad',
type: SourceType.Squad,
active: true,
private: false,
moderationRequired: true,
memberPostingRank: sourceRoleRank[SourceMemberRoles.Member],
memberInviteRank: sourceRoleRank[SourceMemberRoles.Member],
});
await con.getRepository(SquadSource).save([
{
id: 'm',
name: 'Moderated Squad',
image: 'http//image.com/m',
handle: 'moderatedSquad',
type: SourceType.Squad,
active: true,
private: false,
moderationRequired: true,
memberPostingRank: sourceRoleRank[SourceMemberRoles.Member],
memberInviteRank: sourceRoleRank[SourceMemberRoles.Member],
},
{
id: 'm2',
name: 'Second Moderated Squad',
image: 'http//image.com/m2',
handle: 'moderatedSquad2',
type: SourceType.Squad,
active: true,
private: false,
moderationRequired: true,
memberPostingRank: sourceRoleRank[SourceMemberRoles.Member],
memberInviteRank: sourceRoleRank[SourceMemberRoles.Member],
},
]);

await con.getRepository(SourceMember).save([
{
userId: '3',
Expand All @@ -184,6 +199,12 @@ beforeEach(async () => {
role: SourceMemberRoles.Member,
referralToken: randomUUID(),
},
{
userId: '2',
sourceId: 'm2',
role: SourceMemberRoles.Moderator,
referralToken: randomUUID(),
},
]);
await deleteKeysByPattern(`${rateLimiterName}:*`);
});
Expand Down Expand Up @@ -6361,7 +6382,7 @@ describe('query postCodeSnippets', () => {
});

describe('Source post moderation approve/reject', () => {
const [pendingId, rejectedId] = Array.from({ length: 2 }, () =>
const [pendingId, pendingId2, rejectedId] = Array.from({ length: 2 }, () =>
generateUUID(),
);
beforeEach(async () => {
Expand All @@ -6376,6 +6397,15 @@ describe('Source post moderation approve/reject', () => {
status: SourcePostModerationStatus.Pending,
type: PostType.Article,
},
{
id: pendingId2,
sourceId: 'm2',
createdById: '4',
title: 'Title',
content: 'Content',
status: SourcePostModerationStatus.Pending,
type: PostType.Article,
},
{
id: rejectedId,
sourceId: 'm',
Expand All @@ -6395,11 +6425,10 @@ describe('Source post moderation approve/reject', () => {
mutation ModerateSourcePost(
$postIds: [ID]!,
$status: String,
$sourceId: ID!,
$rejectionReason: String,
$moderatorMessage: String
) {
moderateSourcePosts(postIds: $postIds, status: $status, sourceId: $sourceId, rejectionReason: $rejectionReason, moderatorMessage: $moderatorMessage) {
moderateSourcePosts(postIds: $postIds, status: $status, rejectionReason: $rejectionReason, moderatorMessage: $moderatorMessage) {
id
status
}
Expand All @@ -6413,7 +6442,6 @@ describe('Source post moderation approve/reject', () => {
mutation: MUTATION,
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Approved,
},
},
Expand All @@ -6429,7 +6457,6 @@ describe('Source post moderation approve/reject', () => {
mutation: MUTATION,
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Approved,
},
},
Expand All @@ -6445,7 +6472,6 @@ describe('Source post moderation approve/reject', () => {
mutation: MUTATION,
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Approved,
},
},
Expand All @@ -6461,7 +6487,6 @@ describe('Source post moderation approve/reject', () => {
}> = await client.mutate(MUTATION, {
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Approved,
},
});
Expand All @@ -6476,6 +6501,38 @@ describe('Source post moderation approve/reject', () => {
expect(post.moderatedById).toEqual('3');
});

it('should not approve posts in sources where user is not moderator', async () => {
loggedUser = '2'; // Not moderator of "m" squad, which "pendingId" post belongs to.

await testMutationErrorCode(
client,
{
mutation: MUTATION,
variables: {
postIds: [pendingId],
status: SourcePostModerationStatus.Approved,
},
},
'FORBIDDEN',
);
});

it('should throw error when one or more posts in postIds is from a source where user is not moderator', async () => {
loggedUser = '2'; // Not moderator of "m" squad, which "pendingId" post belongs to.

await testMutationErrorCode(
client,
{
mutation: MUTATION,
variables: {
postIds: [pendingId, pendingId2],
status: SourcePostModerationStatus.Approved,
},
},
'FORBIDDEN',
);
});

it('should reject pending posts', async () => {
loggedUser = '3'; // Moderator level

Expand All @@ -6484,7 +6541,6 @@ describe('Source post moderation approve/reject', () => {
}> = await client.mutate(MUTATION, {
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Rejected,
rejectionReason: 'Spam',
moderatorMessage: 'This is spam',
Expand Down Expand Up @@ -6512,7 +6568,6 @@ describe('Source post moderation approve/reject', () => {
mutation: MUTATION,
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Rejected,
moderatorMessage: 'This is spam',
},
Expand All @@ -6530,7 +6585,6 @@ describe('Source post moderation approve/reject', () => {
mutation: MUTATION,
variables: {
postIds: [pendingId],
sourceId: 'm',
status: SourcePostModerationStatus.Rejected,
rejectionReason: 'Other',
},
Expand All @@ -6547,7 +6601,6 @@ describe('Source post moderation approve/reject', () => {
}> = await client.mutate(MUTATION, {
variables: {
postIds: [pendingId, rejectedId],
sourceId: 'm',
status: SourcePostModerationStatus.Approved,
},
});
Expand Down
Loading
Loading