Skip to content

Commit

Permalink
Don't include guest users in the search results
Browse files Browse the repository at this point in the history
Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>
  • Loading branch information
dhenneke committed Sep 15, 2023
1 parent 720f9bc commit c8db19a
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/gorgeous-items-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@nordeck/synapse-guest-module': minor
---

Don't include guest users in the search results.
3 changes: 3 additions & 0 deletions e2e/src/deploy/synapse/homeserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ macaroon_secret_key: '{{MACAROON_SECRET_KEY}}'
form_secret: '{{FORM_SECRET}}'
signing_key_path: '/data/localhost.signing.key'

user_directory:
search_all_users: true

trusted_key_servers:
- server_name: 'matrix.org'
suppress_key_server_warning: true
Expand Down
19 changes: 19 additions & 0 deletions e2e/src/guestLogin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import { expect } from '@playwright/test';
import { test } from './fixtures';
import { registerUser } from './util';

test.describe('Guest Module', () => {
test.beforeEach(({ page: _ }, testInfo) => {
Expand Down Expand Up @@ -187,4 +188,22 @@ test.describe('Guest Module', () => {
/Invites have been disabled on this server/,
);
});

test('should not find guests in Element', async ({ aliceElementWebPage }) => {
await registerUser('guest-example');
await registerUser('normal-example');

const createDirectMessagePage =
await aliceElementWebPage.openCreateDirectMessageDialog();

createDirectMessagePage.search('example');

await expect(
createDirectMessagePage.getSearchResultEntry('normal-example'),
).toBeVisible();

await expect(
createDirectMessagePage.getSearchResultEntry('guest-example'),
).toBeHidden();
});
});
42 changes: 42 additions & 0 deletions e2e/src/pages/createDirectMessagePage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2023 Nordeck IT + Consulting GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Locator, Page } from '@playwright/test';

export class CreateDirectMessagePage {
public readonly dialog: Locator;

constructor(
page: Page,
private readonly startChatButton: Locator,
) {
this.dialog = page.getByRole('dialog', { name: 'Direct Messages' });
}

async open() {
await this.startChatButton.click();

await this.dialog.waitFor();
}

async search(text: string) {
await this.dialog.getByRole('textbox').fill(text);
}

getSearchResultEntry(text: string): Locator {
return this.dialog.getByRole('button', { name: text });
}
}
20 changes: 18 additions & 2 deletions e2e/src/pages/elementWebPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@
import { Locator, Page } from '@playwright/test';
import fetch from 'cross-fetch';
import { Credentials, getElementWebUrl, getSynapseUrl } from '../util';
import { CreateDirectMessagePage } from './createDirectMessagePage';
import { LoginFormPage } from './loginFormPage';
import { UserSettingsPage } from './userSettingsPage';

export class ElementWebPage {
private readonly navigationRegion: Locator;
private readonly mainRegion: Locator;
private readonly headerRegion: Locator;
public readonly roomNameText: Locator;
public readonly userMenuButton: Locator;
private readonly roomNameText: Locator;
private readonly userMenuButton: Locator;
private readonly startChatButton: Locator;

constructor(private readonly page: Page) {
this.navigationRegion = page.getByRole('navigation');
Expand All @@ -35,6 +37,9 @@ export class ElementWebPage {
this.userMenuButton = this.navigationRegion.getByRole('button', {
name: 'User menu',
});
this.startChatButton = this.navigationRegion.getByRole('button', {
name: 'Start chat',
});
}

public getCurrentRoomId(): string {
Expand Down Expand Up @@ -245,6 +250,17 @@ export class ElementWebPage {
return userSettingsPage;
}

public async openCreateDirectMessageDialog(): Promise<CreateDirectMessagePage> {
const createDirectMessagePage = new CreateDirectMessagePage(
this.page,
this.startChatButton,
);

await createDirectMessagePage.open();

return createDirectMessagePage;
}

public getHiddenGuestLocators(): Locator[] {
return [
// Controlled by UIComponent.CreateRooms, UIComponent.ExploreRooms
Expand Down
1 change: 1 addition & 0 deletions synapse-guest-module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ A [pluggable synapse module](https://matrix-org.github.io/synapse/latest/modules
1. Provides an endpoint that creates temporary users with a same pattern (default: `guest-[randomstring]`).
2. The temporary users have a mandatory displayname suffix (default: ` (Guest)`) that they can't remove from their profile.
3. The temporary users are limited in what they can do (examples: create room, invite users).
4. The temporary users won't be returned by the the user directory search results.

## Synapse configuration

Expand Down
12 changes: 11 additions & 1 deletion synapse-guest-module/synapse_guest_module/guest_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import string
from typing import Any, Dict, Optional

from synapse.module_api import ModuleApi, ProfileInfo
from synapse.module_api import ModuleApi, ProfileInfo, UserProfile
from synapse.module_api.errors import ConfigError
from synapse.types import UserID

Expand All @@ -41,6 +41,7 @@ def __init__(self, config: GuestModuleConfig, api: ModuleApi):
self._api.register_spam_checker_callbacks(
user_may_create_room=self.callback_user_may_create_room,
user_may_invite=self.callback_user_may_invite,
check_username_for_spam=self.callback_check_username_for_spam,
)

@staticmethod
Expand Down Expand Up @@ -134,3 +135,12 @@ async def callback_user_may_invite(
"""
user_is_guest = inviter.startswith("@" + self._config.user_id_prefix)
return not user_is_guest

async def callback_check_username_for_spam(self, user_profile: UserProfile) -> bool:
"""Returns whether this user should appear in the user directory. Since
we prefer to not invite guests into normal rooms, we hide them here.
"""
user_is_guest = user_profile["user_id"].startswith(
"@" + self._config.user_id_prefix
)
return user_is_guest
28 changes: 27 additions & 1 deletion synapse-guest-module/tests/test_guest_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

import aiounittest
from synapse.module_api import ProfileInfo
from synapse.module_api import ProfileInfo, UserProfile
from synapse.module_api.errors import ConfigError
from synapse.types import UserID

Expand Down Expand Up @@ -169,3 +169,29 @@ async def test_callback_user_may_invite_guest(self) -> None:
)

self.assertFalse(allow)

async def test_callback_check_username_for_spam_no_guest(self) -> None:
module, _ = create_module()

allow = await module.callback_check_username_for_spam(
UserProfile(
user_id="@my-user:matrix.local",
display_name=None,
avatar_url=None,
),
)

self.assertFalse(allow)

async def test_callback_check_username_for_spam_guest(self) -> None:
module, _ = create_module()

allow = await module.callback_check_username_for_spam(
UserProfile(
user_id="@guest-asdf:matrix.local",
display_name=None,
avatar_url=None,
),
)

self.assertTrue(allow)

0 comments on commit c8db19a

Please sign in to comment.