Skip to content

Commit a15e8c5

Browse files
authored
fix: cache purge behavior for communities (#3528)
1 parent 6de2552 commit a15e8c5

6 files changed

Lines changed: 53 additions & 11 deletions

File tree

client/containers/CommunityCreate/CommunityCreate.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ const CommunityCreate = () => {
145145
setHeroLogo(val);
146146
};
147147

148-
console.log('createError', createError);
149148
return (
150149
<div id="community-create-container">
151150
<GridWrapper containerClassName={isCreated ? undefined : 'small'}>

server/spamTag/api.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ import { Router } from 'express';
55
import { ForbiddenError } from 'server/utils/errors';
66
import { wrap } from 'server/wrap';
77
import { expect } from 'utils/assert';
8+
import { schedulePurge } from 'utils/caching/schedulePurgeWithSentry';
89

910
import { queryCommunitiesForSpamManagement } from './communityDashboard';
1011
import { updateSpamTagForCommunity } from './communityQueries';
1112
import { contextFromUser, notify } from './notifications';
1213
import { canManipulateSpamTags } from './permissions';
13-
import { getRecentDiscussionsForUser, queryUsersForSpamManagement } from './userDashboard';
14+
import {
15+
getAffiliationForUserIds,
16+
getRecentDiscussionsForUser,
17+
queryUsersForSpamManagement,
18+
} from './userDashboard';
1419
import { getSpamTagForUser, removeSpamTagFromUser, upsertSpamTag } from './userQueries';
1520

1621
export const router = Router();
@@ -59,6 +64,16 @@ router.put(
5964
spamFields: spamTag.fields as UserSpamTagFields,
6065
}),
6166
);
67+
68+
// should schedule purges for all communities the user has commented on, ugh
69+
const communities = await getAffiliationForUserIds([userId]);
70+
const communitySubdomains = communities.get(userId)?.communitySubdomains;
71+
if (communitySubdomains) {
72+
for (const communitySubdomain of communitySubdomains) {
73+
schedulePurge(`${communitySubdomain}.pubpub.org`);
74+
}
75+
}
76+
6277
return res.status(200).send({});
6378
}),
6479
);

server/spamTag/communityQueries.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from 'server/utils/email/communitySpam';
99
import { postToSlackAboutCommunityStatusChange } from 'server/utils/slack';
1010
import { expect } from 'utils/assert';
11+
import { schedulePurge } from 'utils/caching/schedulePurgeWithSentry';
1112

1213
import { getSuspectedCommunitySpamVerdict } from './communityScore';
1314

@@ -98,4 +99,6 @@ export const updateSpamTagForCommunity = async (options: UpdateSpamTagForCommuni
9899
subdomain: ctx.communitySubdomain,
99100
status,
100101
});
102+
103+
schedulePurge(`${ctx.communitySubdomain}.pubpub.org`);
101104
};

server/spamTag/userDashboard.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export const queryUsersForSpamManagement = async (
207207
return plain as SerializedSpamUserRow[];
208208
};
209209

210-
const getAffiliationForUserIds = async (
210+
export const getAffiliationForUserIds = async (
211211
userIds: string[],
212212
): Promise<Map<string, types.SpamUserAffiliation>> => {
213213
const [members, attributions, discussions] = await Promise.all([
@@ -251,22 +251,29 @@ const getAffiliationForUserIds = async (
251251
let discussionCount = 0;
252252
for (const m of members) {
253253
if (m.userId === uid) {
254-
const comm = (m as any).community;
255-
if (comm?.subdomain) subdomains.add(comm.subdomain);
254+
const subdomain = m['community.subdomain'];
255+
if (subdomain) {
256+
subdomains.add(subdomain);
257+
}
256258
}
257259
}
258260
for (const a of attributions) {
259261
if (a.userId === uid) {
260262
pubCount += 1;
261-
const pub = (a as any).pub;
262-
if (pub?.community?.subdomain) subdomains.add(pub.community.subdomain);
263+
264+
const subdomain = a['pub.community.subdomain'];
265+
if (subdomain) {
266+
subdomains.add(subdomain);
267+
}
263268
}
264269
}
265270
for (const d of discussions) {
266271
if (d.userId === uid) {
267272
discussionCount += 1;
268-
const pub = (d as any).pub;
269-
if (pub?.community?.subdomain) subdomains.add(pub.community.subdomain);
273+
const subdomain = d['pub.community.subdomain'];
274+
if (subdomain) {
275+
subdomains.add(subdomain);
276+
}
270277
}
271278
}
272279
map.set(uid, {

server/spamTag/userQueries.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import mergeWith from 'lodash.mergewith';
66
import { SpamTag, User } from 'server/models';
77
import { deleteSessionsForUser } from 'server/utils/session';
88
import { expect } from 'utils/assert';
9+
import { schedulePurge } from 'utils/caching/schedulePurgeWithSentry';
910

11+
import { getAffiliationForUserIds } from './userDashboard';
1012
import { getSuspectedUserSpamVerdict } from './userScore';
1113

1214
const mergeSpamTagFields = (
@@ -58,6 +60,17 @@ const invalidateUserSessions = async (user: User) => {
5860
);
5961
};
6062

63+
const schedulePurgesForUser = async (userId: string) => {
64+
// should schedule purges for all communities the user has commented on, ugh
65+
const communities = await getAffiliationForUserIds([userId]);
66+
const communitySubdomains = communities.get(userId)?.communitySubdomains;
67+
if (communitySubdomains) {
68+
for (const communitySubdomain of communitySubdomains) {
69+
schedulePurge(`${communitySubdomain}.pubpub.org`);
70+
}
71+
}
72+
};
73+
6174
export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise<UpsertResult> => {
6275
const { userId, fields, status } = options;
6376
const user = await fetchUserWithSpamTag(userId);
@@ -73,7 +86,7 @@ export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise<Upse
7386
);
7487
await existingTag.update(data as types.SpamVerdict<SpamTag>);
7588
if (status === 'confirmed-spam' && existingTag.status !== status) {
76-
await invalidateUserSessions(user);
89+
await Promise.all([invalidateUserSessions(user), schedulePurgesForUser(userId)]);
7790
}
7891
return { spamTag: existingTag, user };
7992
}
@@ -85,7 +98,7 @@ export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise<Upse
8598
{ where: { id: userId }, limit: 1, individualHooks: false },
8699
);
87100
if (status === 'confirmed-spam') {
88-
await invalidateUserSessions(user);
101+
await Promise.all([invalidateUserSessions(user), schedulePurgesForUser(userId)]);
89102
}
90103
return { spamTag, user };
91104
};

utils/caching/purgeMiddleware.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const nonPurgeNonGetRoutes = {
2626
* (community admin dashboard) Also, otherwise archiving would put a lot of stress on the app
2727
*/
2828
'/api/communities/archive': ['POST'],
29+
// shouldnt purge the community where we access the superadmin dash
30+
'/api/spamTags': ['PUT'],
31+
'/api/spamTags/user': ['DELETE', 'PUT'],
32+
'/api/spamTags/queryCommunitiesForSpam': ['POST'],
33+
'/api/spamTags/userRecentDiscussions': ['POST'],
2934
} satisfies {
3035
[Path in `/api/${string}`]: AllowedMethods[];
3136
};

0 commit comments

Comments
 (0)