diff --git a/CHANGELOG.md b/CHANGELOG.md
index 606f62e59..649e02f31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Environment variable `VERSION` to change the displayed version in the footer ([#3300], [#3302])
- System-wide default welcome message ([#3301])
+- Privacy setting to disable finding users by partial matches of their name or email address ([#2264], [#3316])
### Fixed
@@ -764,6 +765,7 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#2165]: https://github.com/THM-Health/PILOS/pull/2165
[#2222]: https://github.com/THM-Health/PILOS/pull/2222
[#2223]: https://github.com/THM-Health/PILOS/pull/2223
+[#2264]: https://github.com/THM-Health/PILOS/issues/2264
[#2265]: https://github.com/THM-Health/PILOS/issues/2265
[#2279]: https://github.com/THM-Health/PILOS/pull/2279
[#2281]: https://github.com/THM-Health/PILOS/pull/2281
@@ -873,6 +875,7 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#3302]: https://github.com/THM-Health/PILOS/pull/3302
[#3314]: https://github.com/THM-Health/PILOS/issues/3314
[#3315]: https://github.com/THM-Health/PILOS/pull/3315
+[#3316]: https://github.com/THM-Health/PILOS/pull/3316
[unreleased]: https://github.com/THM-Health/PILOS/compare/v4.17.0...develop
[v3.0.0]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.0
[v3.0.1]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.1
diff --git a/app/Http/Controllers/api/v1/SettingsController.php b/app/Http/Controllers/api/v1/SettingsController.php
index bff8927df..c33a375e2 100644
--- a/app/Http/Controllers/api/v1/SettingsController.php
+++ b/app/Http/Controllers/api/v1/SettingsController.php
@@ -189,6 +189,7 @@ public function update(UpdateSettingsRequest $request)
$roomSettings->hide_owner_from_guests = $request->boolean('room_hide_owner_from_guests');
$userSettings->password_change_allowed = $request->boolean('user_password_change_allowed');
+ $userSettings->search_by_name = $request->boolean('user_search_by_name');
$bannerSettings->enabled = $request->boolean('banner_enabled');
$bannerSettings->title = $request->input('banner_title');
diff --git a/app/Http/Controllers/api/v1/UserController.php b/app/Http/Controllers/api/v1/UserController.php
index c25ad099f..5380fff57 100644
--- a/app/Http/Controllers/api/v1/UserController.php
+++ b/app/Http/Controllers/api/v1/UserController.php
@@ -19,6 +19,7 @@
use App\Services\AuthenticationService;
use App\Services\EmailVerification\EmailVerificationService;
use App\Settings\GeneralSettings;
+use App\Settings\UserSettings;
use Carbon\Carbon;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
@@ -31,6 +32,7 @@
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Str;
class UserController extends Controller
{
@@ -41,18 +43,28 @@ public function __construct()
}
/**
- * Search for users in the whole database, based on first name and last name
+ * Search for users in the whole database
+ * Depending on the search_by_name setting it will either search for partial matches of firstname, lastname and email
+ * or only for an exact email match
*
* @param UserSearchRequest $request query parameter with search query
* @return AnonymousResourceCollection
*/
public function search(UserSearchRequest $request)
{
+ $userSettings = app(UserSettings::class);
+
if (! $request->filled('query')) {
abort(204, 'Too many results');
}
- $query = User::withNameOrEmail($request->query('query'));
+ if ($userSettings->search_by_name) {
+ $query = User::withNameOrEmail($request->query('query'));
+ } else {
+ // Escape wildcard characters and escape backslashes to prevent escaping our added escape backslash
+ $email = Str::replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $request->query('query'));
+ $query = User::whereLike('email', $email);
+ }
if ($query->count() > config('bigbluebutton.user_search_limit')) {
abort(204, 'Too many results');
diff --git a/app/Http/Requests/UpdateSettingsRequest.php b/app/Http/Requests/UpdateSettingsRequest.php
index 9ae7803d0..6091d9725 100644
--- a/app/Http/Requests/UpdateSettingsRequest.php
+++ b/app/Http/Requests/UpdateSettingsRequest.php
@@ -75,6 +75,7 @@ public function rules()
'room_hide_owner_from_guests' => ['required', 'boolean'],
'user_password_change_allowed' => ['required', 'boolean'],
+ 'user_search_by_name' => ['required', 'boolean'],
'recording_server_usage_enabled' => ['required', 'boolean'],
'recording_server_usage_retention_period' => ['required', 'numeric', Rule::enum(TimePeriod::class)],
diff --git a/app/Http/Resources/ConfigResource.php b/app/Http/Resources/ConfigResource.php
index dd529a9c1..c9236037c 100644
--- a/app/Http/Resources/ConfigResource.php
+++ b/app/Http/Resources/ConfigResource.php
@@ -69,6 +69,7 @@ public function toArray($request)
],
'user' => [
'password_change_allowed' => $userSettings->password_change_allowed,
+ 'search_by_name' => $userSettings->search_by_name,
],
'bbb' => [
'file_mimes' => config('bigbluebutton.allowed_file_mimes'),
diff --git a/app/Http/Resources/SettingsResource.php b/app/Http/Resources/SettingsResource.php
index 52f1b5880..5935cf606 100644
--- a/app/Http/Resources/SettingsResource.php
+++ b/app/Http/Resources/SettingsResource.php
@@ -70,6 +70,7 @@ public function toArray($request)
'room_file_terms_of_use' => $roomSettings->file_terms_of_use,
'room_hide_owner_from_guests' => $roomSettings->hide_owner_from_guests,
'user_password_change_allowed' => $userSettings->password_change_allowed,
+ 'user_search_by_name' => $userSettings->search_by_name,
'recording_server_usage_enabled' => $recordingSettings->server_usage_enabled,
'recording_server_usage_retention_period' => $recordingSettings->server_usage_retention_period,
'recording_meeting_usage_enabled' => $recordingSettings->meeting_usage_enabled,
diff --git a/app/Settings/UserSettings.php b/app/Settings/UserSettings.php
index 4a5c2313e..8ebca456e 100644
--- a/app/Settings/UserSettings.php
+++ b/app/Settings/UserSettings.php
@@ -10,6 +10,8 @@ class UserSettings extends Settings
{
public bool $password_change_allowed;
+ public bool $search_by_name;
+
public static function group(): string
{
return 'user';
diff --git a/database/settings/2026_07_15_130614_add_user_search_by_name.php b/database/settings/2026_07_15_130614_add_user_search_by_name.php
new file mode 100644
index 000000000..d7be415db
--- /dev/null
+++ b/database/settings/2026_07_15_130614_add_user_search_by_name.php
@@ -0,0 +1,18 @@
+migrator->add('user.search_by_name', true);
+ }
+
+ public function down(): void
+ {
+ $this->migrator->delete('user.search_by_name');
+ }
+};
diff --git a/lang/en/admin.php b/lang/en/admin.php
index 776656a68..adbadfb7c 100644
--- a/lang/en/admin.php
+++ b/lang/en/admin.php
@@ -426,6 +426,10 @@
],
'two_weeks' => '2 Weeks (14 Days)',
'two_years' => '2 Years (730 Days)',
+ 'user_search_by_name' => [
+ 'description' => 'Allows users to find others by partial matches of their name or email address. When disabled, users can only be found by entering their exact email address.',
+ 'title' => 'Allow searching users by name',
+ ],
'user_settings' => 'User settings',
],
'streaming' => [
diff --git a/lang/en/rooms.php b/lang/en/rooms.php
index 238a8a87f..2da3f25fd 100644
--- a/lang/en/rooms.php
+++ b/lang/en/rooms.php
@@ -222,8 +222,11 @@
'add' => [
'add' => 'Add',
'no_options' => 'Enter the name or email address of a user.',
+ 'no_options_email_only' => 'Enter the email address of a user.',
'no_result' => 'Oops! No user was found for this query.',
'placeholder' => 'Name or email',
+ 'placeholder_email_only' => 'Email',
+ 'searching' => 'Searching...',
'select_role' => 'Please select a role',
'select_user' => 'Please select the user you would like to add',
'too_many_results' => 'Too many users were found. Please enter a more precise search term.',
diff --git a/resources/js/components/RoomTabMembersAddSingleModal.vue b/resources/js/components/RoomTabMembersAddSingleModal.vue
index 038740d52..ca0deb3ae 100644
--- a/resources/js/components/RoomTabMembersAddSingleModal.vue
+++ b/resources/js/components/RoomTabMembersAddSingleModal.vue
@@ -39,51 +39,13 @@
-
-
-
- {{ $t("rooms.members.modals.add.too_many_results") }}
-
-
- {{ $t("rooms.members.modals.add.no_result") }}
-
-
-
- {{ $t("rooms.members.modals.add.no_options") }}
-
-
- {{ option.firstname }} {{ option.lastname }}
{{
- option.email
- }}
-
-
- {{ option.firstname }} {{ option.lastname }}
-
-
+ />
@@ -144,7 +106,6 @@
diff --git a/resources/js/components/UserSearch.vue b/resources/js/components/UserSearch.vue
new file mode 100644
index 000000000..fffdad158
--- /dev/null
+++ b/resources/js/components/UserSearch.vue
@@ -0,0 +1,153 @@
+
+
+
+
+ {{ $t("rooms.members.modals.add.too_many_results") }}
+
+
+ {{ $t("rooms.members.modals.add.no_result") }}
+
+
+
+
+ {{ $t("rooms.members.modals.add.searching") }}
+
+
+
+ {{
+ settingsStore.getSetting("user.search_by_name")
+ ? $t("rooms.members.modals.add.no_options")
+ : $t("rooms.members.modals.add.no_options_email_only")
+ }}
+
+
+ {{ option.firstname }} {{ option.lastname }}
{{
+ option.email
+ }}
+
+
+ {{ option.firstname }} {{ option.lastname }}
+
+
+
+
diff --git a/resources/js/views/AdminSettings.vue b/resources/js/views/AdminSettings.vue
index 96cc6c588..ee779f2e9 100644
--- a/resources/js/views/AdminSettings.vue
+++ b/resources/js/views/AdminSettings.vue
@@ -1151,6 +1151,36 @@
/>
+
+
roomSettings->save();
$this->userSettings->password_change_allowed = true;
+ $this->userSettings->search_by_name = true;
$this->userSettings->save();
$this->recordingSettings->server_usage_enabled = true;
@@ -164,6 +166,7 @@ public function test_view_settings()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => true,
+ 'user_search_by_name' => true,
'recording_server_usage_enabled' => true,
'recording_server_usage_retention_period' => 7,
@@ -228,6 +231,7 @@ public function test_update_settings()
'room_hide_owner_from_guests' => true,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -292,6 +296,7 @@ public function test_update_settings()
'room_hide_owner_from_guests' => true,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -309,12 +314,14 @@ public function test_update_settings()
$this->assertEquals('http://localhost', app(GeneralSettings::class)->legal_notice_url);
$this->assertEquals('http://localhost', app(GeneralSettings::class)->privacy_policy_url);
$this->assertEquals('http://localhost', app(GeneralSettings::class)->accessibility_statement_url);
+ $this->assertTrue(app(UserSettings::class)->search_by_name);
$payload['general_help_url'] = '';
$payload['general_legal_notice_url'] = '';
$payload['general_privacy_policy_url'] = '';
$payload['general_accessibility_statement_url'] = '';
$payload['room_file_terms_of_use'] = '';
+ $payload['user_search_by_name'] = 0;
$payload['bbb_default_welcome_message'] = '';
$this->putJson(route('api.v1.settings.update'), $payload)
@@ -325,6 +332,7 @@ public function test_update_settings()
$this->assertNull(app(GeneralSettings::class)->privacy_policy_url);
$this->assertNull(app(GeneralSettings::class)->accessibility_statement_url);
$this->assertNull(app(RoomSettings::class)->file_terms_of_use);
+ $this->assertFalse(app(UserSettings::class)->search_by_name);
$this->assertNull(app(BigBlueButtonSettings::class)->default_welcome_message);
}
@@ -373,6 +381,7 @@ public function test_update_with_valid_inputs_image_file()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -452,6 +461,7 @@ public function test_update_with_valid_inputs_image_file_and_url()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -535,6 +545,7 @@ public function test_update_with_invalid_inputs()
'room_hide_owner_from_guests' => 'notbool',
'user_password_change_allowed' => 'foo',
+ 'user_search_by_name' => 'foo',
'recording_server_usage_enabled' => 'foo',
'recording_server_usage_retention_period' => 'notnumber',
@@ -589,6 +600,7 @@ public function test_update_with_invalid_inputs()
'room_hide_owner_from_guests',
'user_password_change_allowed',
+ 'user_search_by_name',
'recording_server_usage_enabled',
'recording_server_usage_retention_period',
@@ -673,6 +685,7 @@ public function test_update_theme_custom_css()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -780,6 +793,7 @@ public function test_update_min_max()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 1,
@@ -835,6 +849,7 @@ public function test_update_min_max()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 366,
@@ -917,6 +932,7 @@ public function test_update_default_presentation()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -1029,6 +1045,7 @@ public function test_update_bbb_style()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -1126,6 +1143,7 @@ public function test_update_bbb_logo()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -1210,6 +1228,7 @@ public function test_update_bbb_dark_logo()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
@@ -1300,6 +1319,7 @@ public function test_virus_files()
'room_hide_owner_from_guests' => false,
'user_password_change_allowed' => 1,
+ 'user_search_by_name' => 1,
'recording_server_usage_enabled' => 0,
'recording_server_usage_retention_period' => 7,
diff --git a/tests/Backend/Feature/api/v1/UserTest.php b/tests/Backend/Feature/api/v1/UserTest.php
index 12e4ad94a..40c29d11d 100644
--- a/tests/Backend/Feature/api/v1/UserTest.php
+++ b/tests/Backend/Feature/api/v1/UserTest.php
@@ -14,6 +14,7 @@
use App\Notifications\PasswordReset;
use App\Notifications\UserWelcome;
use App\Notifications\VerifyEmail;
+use App\Settings\UserSettings;
use Carbon\Carbon;
use Database\Seeders\RolesAndPermissionsSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -198,6 +199,10 @@ public function test_search()
$searchLimit = 5;
config(['bigbluebutton.user_search_limit' => $searchLimit]);
+ $userSettings = app(UserSettings::class);
+ $userSettings->search_by_name = true;
+ $userSettings->save();
+
$users = [];
$users[] = User::factory()->create(['firstname' => 'Gregory', 'lastname' => 'Dumas', 'email' => 'gregory.dumas@example.com']);
$users[] = User::factory()->create(['firstname' => 'Mable', 'lastname' => 'Torres', 'email' => 'mable.torres@example.com']);
@@ -254,6 +259,69 @@ public function test_search()
->assertJsonCount(1, 'data');
}
+ public function test_search_by_name_disabled()
+ {
+ $searchLimit = 5;
+ config(['bigbluebutton.user_search_limit' => $searchLimit]);
+
+ $userSettings = app(UserSettings::class);
+ $userSettings->search_by_name = false;
+ $userSettings->save();
+
+ $users = [];
+ $users[] = User::factory()->create(['firstname' => 'Gregory', 'lastname' => 'Dumas', 'email' => 'gregory.dumas@example.com']);
+
+ // Check with exact lastname match (search for names should not be possible)
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=Dumas')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Check with exact firstname match (search for names should not be possible)
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=Gregory')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Check fragments of email (query must match exactly, fragments are disabled)
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=example.com')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Check exact email (case-insensitive)
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=Gregory.Dumas@example.com')
+ ->assertSuccessful()
+ ->assertJsonPath('data.0.firstname', $users[0]->firstname)
+ ->assertJsonCount(1, 'data');
+
+ // Check wildcard characters are treated literally and do not perform pattern matching
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=gregory%')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=gregory_dumas@example.com')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Check if adding a backslash cannot bypass the escaping
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=gregory\%')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Add \ to email and test if it cannot bypass the escaping
+ $users[0]->email = 'gregory\.dumas@example.com';
+ $users[0]->save();
+
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=gregory\%')
+ ->assertSuccessful()
+ ->assertJsonCount(0, 'data');
+
+ // Check if email with all chars can still be found
+ $users[0]->email = 'gregory\_%.dumas@example.com';
+ $users[0]->save();
+
+ $this->actingAs($users[0])->getJson(route('api.v1.users.search').'?query=gregory\_%.dumas@example.com')
+ ->assertSuccessful()
+ ->assertJsonCount(1, 'data');
+ }
+
public function test_create()
{
$user = User::factory()->create();
diff --git a/tests/Frontend/e2e/AdminSettingsEdit.cy.js b/tests/Frontend/e2e/AdminSettingsEdit.cy.js
index 3c22a5f2d..ec3e689a1 100644
--- a/tests/Frontend/e2e/AdminSettingsEdit.cy.js
+++ b/tests/Frontend/e2e/AdminSettingsEdit.cy.js
@@ -2279,9 +2279,17 @@ describe("Admin settings with edit permission", function () {
cy.get("#password-change-allowed").should("be.checked").click();
});
+ cy.get('[data-test="user-search-by-name-field"]')
+ .should("be.visible")
+ .and("include.text", "admin.settings.user_search_by_name.title")
+ .within(() => {
+ cy.get("#user-search-by-name").should("be.checked").click();
+ });
+
// Save changes
cy.fixture("settings.json").then((settings) => {
settings.data.user_password_change_allowed = false;
+ settings.data.user_search_by_name = false;
const saveChangesRequest = interceptIndefinitely(
"POST",
@@ -2313,6 +2321,7 @@ describe("Admin settings with edit permission", function () {
);
expect(formData.get("user_password_change_allowed")).to.equal("0");
+ expect(formData.get("user_search_by_name")).to.equal("0");
});
// Check that config is loaded
@@ -2324,6 +2333,7 @@ describe("Admin settings with edit permission", function () {
// Check that settings are shown correctly
cy.get("#password-change-allowed").should("not.be.checked");
+ cy.get("#user-search-by-name").should("not.be.checked");
});
it("change recording and statistics settings", function () {
diff --git a/tests/Frontend/e2e/AdminSettingsView.cy.js b/tests/Frontend/e2e/AdminSettingsView.cy.js
index 32274e4e2..a5525e57a 100644
--- a/tests/Frontend/e2e/AdminSettingsView.cy.js
+++ b/tests/Frontend/e2e/AdminSettingsView.cy.js
@@ -727,6 +727,48 @@ describe("Admin settings with edit permission", function () {
.should("be.checked")
.and("be.disabled");
});
+
+ cy.get('[data-test="user-search-by-name-field"]')
+ .should("be.visible")
+ .and("include.text", "admin.settings.user_search_by_name.title")
+ .and("include.text", "admin.settings.user_search_by_name.description")
+ .within(() => {
+ cy.get("#user-search-by-name").should("be.checked").and("be.disabled");
+ });
+
+ // Reload with different settings
+ cy.fixture("settings.json").then((settings) => {
+ settings.data.user_password_change_allowed = false;
+ settings.data.user_search_by_name = false;
+
+ cy.intercept("GET", "api/v1/settings", {
+ statusCode: 200,
+ body: settings,
+ }).as("settingsRequest");
+ });
+
+ cy.reload();
+
+ cy.wait("@settingsRequest");
+
+ cy.get('[data-test="password-change-allowed-field"]')
+ .should("be.visible")
+ .and("include.text", "admin.settings.password_change_allowed")
+ .within(() => {
+ cy.get("#password-change-allowed")
+ .should("not.be.checked")
+ .and("be.disabled");
+ });
+
+ cy.get('[data-test="user-search-by-name-field"]')
+ .should("be.visible")
+ .and("include.text", "admin.settings.user_search_by_name.title")
+ .and("include.text", "admin.settings.user_search_by_name.description")
+ .within(() => {
+ cy.get("#user-search-by-name")
+ .should("not.be.checked")
+ .and("be.disabled");
+ });
});
it("check recording and statistics settings with only view permission", function () {
diff --git a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
index 0971e4743..31f3a75e9 100644
--- a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
@@ -94,22 +94,6 @@ describe("Rooms view members member actions", function () {
cy.get('[data-test="select-user-dropdown"]').find("input").type("aura");
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "La",
- });
- });
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "Lau",
- });
- });
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "Laur",
- });
- });
-
cy.wait("@userSearchRequest").then((interception) => {
expect(interception.request.query).to.contain({
query: "Laura",
@@ -241,6 +225,45 @@ describe("Rooms view members member actions", function () {
.should("include.text", "rooms.roles.moderator");
});
+ it("add new member with search by name disabled", function () {
+ cy.fixture("config.json").then((config) => {
+ config.data.user.search_by_name = false;
+
+ cy.intercept("GET", "api/v1/config", {
+ statusCode: 200,
+ body: config,
+ });
+ });
+
+ cy.visit("/rooms/abc-def-123#tab=members");
+
+ cy.wait("@roomMembersRequest");
+
+ cy.get('[data-test="room-members-add-button"]').click();
+
+ // Click on add single user option
+ cy.get("#overlay_menu_0")
+ .should("have.text", "rooms.members.add_single_user")
+ .click();
+
+ cy.get('[data-test="room-members-add-single-dialog"]').should("be.visible");
+
+ // Check prompt
+ cy.get('[data-test="select-user-dropdown"]').should(
+ "include.text",
+ "rooms.members.modals.add.no_options_email_only",
+ );
+
+ // Check placeholder
+ cy.get('[data-test="select-user-dropdown"]')
+ .find("input")
+ .should(
+ "have.attr",
+ "placeholder",
+ "rooms.members.modals.add.placeholder_email_only",
+ );
+ });
+
it("add new member errors", function () {
cy.visit("/rooms/abc-def-123#tab=members");
cy.wait("@roomRequest");
diff --git a/tests/Frontend/e2e/RoomsViewSettings.cy.js b/tests/Frontend/e2e/RoomsViewSettings.cy.js
index 9cf9991a3..ed82c41ef 100644
--- a/tests/Frontend/e2e/RoomsViewSettings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewSettings.cy.js
@@ -1926,7 +1926,11 @@ describe("Rooms view settings", function () {
// Check placeholder and type in input
cy.get('[data-test="new-owner-dropdown"]')
.find("input")
- .should("have.attr", "placeholder", "app.user_name")
+ .should(
+ "have.attr",
+ "placeholder",
+ "rooms.members.modals.add.placeholder",
+ )
.click();
cy.get('[data-test="new-owner-dropdown"]').find("input").type("L");
@@ -1980,22 +1984,6 @@ describe("Rooms view settings", function () {
cy.get('[data-test="new-owner-dropdown"]').find("input").type("aura");
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "La",
- });
- });
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "Lau",
- });
- });
- cy.wait("@userSearchRequest").then((interception) => {
- expect(interception.request.query).to.contain({
- query: "Laur",
- });
- });
-
cy.wait("@userSearchRequest").then((interception) => {
expect(interception.request.query).to.contain({
query: "Laura",
@@ -2199,6 +2187,49 @@ describe("Rooms view settings", function () {
cy.get('[data-test="room-access-code-overlay"]').should("be.visible");
});
+ it("transfer ownership with search by name disabled", function () {
+ cy.fixture("config.json").then((config) => {
+ config.data.user.search_by_name = false;
+
+ cy.intercept("GET", "api/v1/config", {
+ statusCode: 200,
+ body: config,
+ });
+ });
+
+ cy.visit("/rooms/abc-def-123#tab=settings");
+
+ cy.wait("@roomSettingsRequest");
+
+ cy.get("[data-test=room-transfer-ownership-dialog]").should("not.exist");
+ cy.get('[data-test="room-transfer-ownership-button"]')
+ .should("have.text", "rooms.modals.transfer_ownership.title")
+ .click();
+
+ // Check that dialog is shown correctly
+ cy.get("[data-test=room-transfer-ownership-dialog]")
+ .should("be.visible")
+ .within(() => {
+ // Check autofocus
+ cy.get(".multiselect__content").should("be.visible");
+
+ // Check prompt
+ cy.get('[data-test="new-owner-dropdown"]').should(
+ "include.text",
+ "rooms.members.modals.add.no_options_email_only",
+ );
+
+ // Check placeholder
+ cy.get('[data-test="new-owner-dropdown"]')
+ .find("input")
+ .should(
+ "have.attr",
+ "placeholder",
+ "rooms.members.modals.add.placeholder_email_only",
+ );
+ });
+ });
+
it("transfer ownership errors", function () {
cy.visit("/rooms/abc-def-123#tab=settings");
diff --git a/tests/Frontend/fixtures/config.json b/tests/Frontend/fixtures/config.json
index 74c9bf878..d3dfe047b 100644
--- a/tests/Frontend/fixtures/config.json
+++ b/tests/Frontend/fixtures/config.json
@@ -35,7 +35,8 @@
"room_name_limit": 50
},
"user": {
- "password_change_allowed": true
+ "password_change_allowed": true,
+ "search_by_name": true
},
"banner": {},
"recording": {
diff --git a/tests/Frontend/fixtures/settings.json b/tests/Frontend/fixtures/settings.json
index 798a5c52a..e18541d17 100644
--- a/tests/Frontend/fixtures/settings.json
+++ b/tests/Frontend/fixtures/settings.json
@@ -33,6 +33,7 @@
"room_file_terms_of_use": "Room file terms of use",
"room_hide_owner_from_guests": false,
"user_password_change_allowed": true,
+ "user_search_by_name": true,
"recording_server_usage_enabled": true,
"recording_server_usage_retention_period": -1,
"recording_meeting_usage_enabled": true,