UI: Add support for usernames with @ symbol

This commit is contained in:
Max Berger
2026-04-25 21:21:10 +02:00
parent 146d4b4a9a
commit f1af26a798
8 changed files with 67 additions and 36 deletions

View File

@@ -47,6 +47,8 @@ class Config:
auth_type: AuthType
sharing_type: SharingType
extra_config: str = ""
admin_username: str = "admin"
user_username: str = "max"
SHARING_HTPASSWD = Config(
@@ -55,6 +57,14 @@ SHARING_HTPASSWD = Config(
sharing_type=SharingType.SHARING,
)
SHARING_HTPASSWD_USERSWITHDOMAIN = Config(
name="sharing_htpasswd_userswithdomain",
auth_type=AuthType.HTPASSWD,
sharing_type=SharingType.SHARING,
admin_username="admin@domain.tld",
user_username="max@domain.tld",
)
SHARING_XREMOTE = Config(
name="sharing_xremote",
auth_type=AuthType.XREMOTE,
@@ -122,12 +132,8 @@ database_path = {sharing_path}
if config.auth_type == AuthType.HTPASSWD:
with open(user_path, "w") as f:
f.write(
"""admin:admi$pass#word
max:maxpassword
"""
)
f.write(f"{config.admin_username}:admi$pass#word\n")
f.write(f"{config.user_username}:userpassword\n")
env = os.environ.copy()
# Ensure the radicale package is in PYTHONPATH
@@ -182,7 +188,7 @@ def login(
page.goto(radicale_server)
if config.auth_type == AuthType.HTPASSWD:
page.fill('#loginscene input[data-name="user"]', "admin")
page.fill('#loginscene input[data-name="user"]', config.admin_username)
page.fill('#loginscene input[data-name="password"]', "admi$pass#word")
page.click('button:has-text("Next")')

View File

@@ -25,25 +25,38 @@ from typing import Any, Generator
import pytest
from playwright.sync_api import Page, expect
from integ_tests.common import (SHARING_HTPASSWD, create_collection, login,
from integ_tests.common import (SHARING_HTPASSWD,
SHARING_HTPASSWD_USERSWITHDOMAIN, Config,
create_collection, login,
start_radicale_server)
@pytest.fixture(params=[SHARING_HTPASSWD, SHARING_HTPASSWD_USERSWITHDOMAIN])
def radicale_server_config(request: pytest.FixtureRequest) -> Config:
return request.param
@pytest.fixture
def radicale_server(tmp_path: pathlib.Path) -> Generator[str, Any, None]:
yield from start_radicale_server(tmp_path, SHARING_HTPASSWD)
def radicale_server(
tmp_path: pathlib.Path, radicale_server_config: Config
) -> Generator[str, Any, None]:
yield from start_radicale_server(tmp_path, radicale_server_config)
@pytest.mark.parametrize("permissions", ["ro", "rw"])
def test_incoming_shares(page: Page, radicale_server: str, permissions: str) -> None:
def test_incoming_shares(
page: Page, radicale_server: str, radicale_server_config: Config, permissions: str
) -> None:
# 1. Admin logs in and creates a map share for 'max'
login(page, radicale_server, SHARING_HTPASSWD)
login(page, radicale_server, radicale_server_config)
create_collection(page, radicale_server)
page.hover("article:not(.hidden)")
page.click('article:not(.hidden) a[data-name="share"]', force=True, strict=True)
page.click('button[data-name="sharebymap"]')
page.locator('input[data-name="shareuser"]').fill("max")
page.locator('input[data-name="shareuser"]').fill(
radicale_server_config.user_username
)
page.locator('input[data-name="sharehref"]').fill("mapped")
if permissions == "rw":
page.check("#newshare_attr_permissions_rw")
@@ -57,8 +70,10 @@ def test_incoming_shares(page: Page, radicale_server: str, permissions: str) ->
page.click('a[data-name="logout"]')
# 3. Max logs in
page.fill('#loginscene input[data-name="user"]', "max")
page.fill('#loginscene input[data-name="password"]', "maxpassword")
page.fill(
'#loginscene input[data-name="user"]', radicale_server_config.user_username
)
page.fill('#loginscene input[data-name="password"]', "userpassword")
page.click('button:has-text("Next")')
# 4. Max sees the incoming share
@@ -118,7 +133,9 @@ def test_incoming_shares(page: Page, radicale_server: str, permissions: str) ->
article = page.locator("article:not(.hidden)").first
expect(article.locator('[data-name="shared-by"]')).to_be_visible()
expect(article.locator('[data-name="shared-by-owner"]')).to_have_text("admin")
expect(article.locator('[data-name="shared-by-owner"]')).to_have_text(
radicale_server_config.admin_username
)
# Action buttons are only visible on mouseover
article.hover()
@@ -138,11 +155,15 @@ def test_incoming_shares(page: Page, radicale_server: str, permissions: str) ->
expect(page.locator('#incomingsharingscene span[data-name="error"]')).to_be_hidden()
def test_no_incoming_shares_message(page: Page, radicale_server: str) -> None:
def test_no_incoming_shares_message(
page: Page, radicale_server: str, radicale_server_config: Config
) -> None:
# 1. Max logs in
page.goto(radicale_server)
page.fill('#loginscene input[data-name="user"]', "max")
page.fill('#loginscene input[data-name="password"]', "maxpassword")
page.fill(
'#loginscene input[data-name="user"]', radicale_server_config.user_username
)
page.fill('#loginscene input[data-name="password"]', "userpassword")
page.click('button:has-text("Next")')
# 2. Max goes to incoming shares scene