Skip to content

Commit

Permalink
fix: anonymous authors and mentioning on search
Browse files Browse the repository at this point in the history
  • Loading branch information
sandrodesouza committed Mar 3, 2023
1 parent cac7b50 commit 997aff6
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 24 deletions.
115 changes: 115 additions & 0 deletions apps/web/__tests__/pages/api/search.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { accounts, AccountType, users } from '@linen/database';
import {
createAccount,
createChannel,
createThread,
createMessage,
createUser,
} from '@linen/factory';
import handlerSearch from 'pages/api/search';
import { testApiHandler } from 'next-test-api-route-handler';
import { qs } from '@linen/utilities/url';

function cleanMock() {}

type storeType = {
account: accounts;
user: users;
};

describe('search', () => {
describe('anonymous community', () => {
const store: storeType = {} as any;

beforeAll(async () => {
store.account = await createAccount({
type: AccountType.PUBLIC,
anonymizeUsers: true,
});
const channel = await createChannel({
accountId: store.account.id,
hidden: false,
});
store.user = await createUser({
accountsId: store.account.id,
displayName: 'cool-name',
anonymousAlias: 'hidden-name',
});
const thread = await createThread({ channelId: channel.id });
await createMessage({
body: 'test',
channelId: channel.id,
threadId: thread.id,
usersId: store.user.id,
});

await createMessage({
body: `hello @${store.user.id}`,
channelId: channel.id,
threadId: thread.id,
usersId: store.user.id,
mentions: {
createMany: { data: [{ usersId: store.user.id }] },
},
} as any);

cleanMock();
});

test('author information should be hidden', async () => {
await testApiHandler({
handler: handlerSearch,
url: `/api/search?${qs({
account_id: store.account.id,
query: 'test',
limit: 1,
offset: 0,
})}`,
test: async ({ fetch }) => {
const response = await fetch({
method: 'GET',
});
expect(response.status).toEqual(200);
const body = await response.json();
expect(body).toHaveLength(1);
expect(body[0].user.displayName).toBe(store.user.anonymousAlias);
expect(body[0].user.username).toBe(store.user.anonymousAlias);
expect(body[0].user.profileImageUrl).toBe(null);
},
});
});

test('mentioned user should be hidden', async () => {
await testApiHandler({
handler: handlerSearch,
url: `/api/search?${qs({
account_id: store.account.id,
query: 'hello',
limit: 1,
offset: 0,
})}`,
test: async ({ fetch }) => {
const response = await fetch({
method: 'GET',
});
expect(response.status).toEqual(200);
const body = await response.json();
expect(body).toHaveLength(1);
expect(body[0].user.displayName).toBe(store.user.anonymousAlias);
expect(body[0].user.username).toBe(store.user.anonymousAlias);
expect(body[0].user.profileImageUrl).toBe(null);

expect(body[0].mentions).toHaveLength(1);
const mention = body[0].mentions[0];
expect(mention.displayName).toBe(store.user.anonymousAlias);
expect(mention.username).toBe(store.user.anonymousAlias);
expect(mention.profileImageUrl).toBe(null);
},
});
});

afterAll(() => {
cleanMock();
});
});
});
28 changes: 16 additions & 12 deletions apps/web/pages/api/search.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { anonymizeMessagesMentions } from 'utilities/anonymizeMessages';
import { anonymizeUser } from 'utilities/anonymizeMessages';
import { NextApiRequest, NextApiResponse } from 'next/types';
import {
messages,
Expand All @@ -12,6 +12,7 @@ import {
import PermissionsService from 'services/permissions';
import unique from 'lodash.uniq';
import serializeUser from 'serializers/user';
import { SerializedUser } from '@linen/types';

async function handler(req: NextApiRequest, res: NextApiResponse) {
const query = req.query.query as string;
Expand Down Expand Up @@ -109,7 +110,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
"public"."users"."anonymousAlias",
"public"."users"."accountsId"
FROM "public"."users"
WHERE "public"."users"."id" IN (${Prisma.join(userIds)})`
WHERE "public"."users"."id" IN (${Prisma.join(userIds)})`.then((users) => {
if (!!account?.anonymizeUsers) {
return users.map((u) => anonymizeUser(u));
}
return users;
})
: [];

// Map the results
Expand All @@ -119,17 +125,15 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
...mr,
threads: threadsResult.find((str) => str.id === mr.threadId),
user: user ? serializeUser(user) : null,
mentions: mentionsResult.map((msr) => {
return {
...msr,
users: usersResult.find((ur) => ur.id === msr.usersId),
};
}),
mentions: mentionsResult.reduce((prev, curr) => {
const users = usersResult.find((ur) => ur.id === curr.usersId);
if (users) {
return [...prev, serializeUser(users)];
}
return prev;
}, [] as SerializedUser[]),
};
});
const response = !!account?.anonymizeUsers
? anonymizeMessagesMentions(searchResults as any)
: searchResults;

// Below is the Prisma substitute of the obove series of queries
// but Prisma is not using full-text GIS index, and it is extremely slow.
Expand Down Expand Up @@ -165,7 +169,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// }
// });

res.status(200).json(response);
res.status(200).json(searchResults);
}

//generated by taking matches and passing it in to json to typescript
Expand Down
22 changes: 10 additions & 12 deletions apps/web/utilities/anonymizeMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,7 @@ export function anonymizeMessages(thread: ThreadWithMessages) {
if (thread) {
thread.messages = thread.messages.map((message) => {
if (message.author) {
message.author = {
...message.author,
displayName:
(message.author?.anonymousAlias as string) || 'anonymous',
profileImageUrl: null,
};
message.author = anonymizeUser(message.author);
}

return anonymizeMentions(message);
Expand All @@ -44,18 +39,21 @@ export function anonymizeMessages(thread: ThreadWithMessages) {
function anonymizeMentions(message: Messages): any {
if (message.mentions) {
message.mentions = message.mentions.map((mention) => {
mention.users &&
(mention.users = {
...mention.users,
displayName: mention.users.anonymousAlias || 'anonymous',
profileImageUrl: null,
});
mention.users && (mention.users = anonymizeUser(mention.users));
return mention;
});
}
return message;
}

export function anonymizeUser(users: users): users {
return {
...users,
displayName: users.anonymousAlias || 'anonymous',
profileImageUrl: null,
};
}

export function anonymizeMessagesMentions(messages: Messages[]) {
return messages.map((message) => {
return anonymizeMentions(message);
Expand Down

0 comments on commit 997aff6

Please sign in to comment.