fix: change livkit udp ports and add ttl for livekit token
This commit is contained in:
parent
6d687e7361
commit
720f8e6b7c
|
|
@ -38,5 +38,5 @@ class RateLimiter:
|
||||||
# But Starlette's HTTPException is also handled by FastAPI for WebSockets by closing the connection.
|
# But Starlette's HTTPException is also handled by FastAPI for WebSockets by closing the connection.
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
||||||
detail="Too many requests. Please try again later."
|
detail="تعداد درخواستهای شما از حد مجاز گذشته است. لطفاً بعداً دوباره تلاش کنید."
|
||||||
)
|
)
|
||||||
|
|
@ -42,7 +42,7 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "7780:7880"
|
- "7780:7880"
|
||||||
- "7781:7881"
|
- "7781:7881"
|
||||||
- "51000-51100:51000-51100/udp"
|
- "51000-52000:51000-52000/udp"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from livekit import api
|
from livekit import api
|
||||||
|
|
||||||
from core.config import settings
|
from core.config import settings
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
def generate_join_token(
|
def generate_join_token(
|
||||||
user_id: str,
|
user_id: str,
|
||||||
|
|
@ -15,6 +15,7 @@ def generate_join_token(
|
||||||
)
|
)
|
||||||
|
|
||||||
token.with_identity(user_id)
|
token.with_identity(user_id)
|
||||||
|
token.with_ttl(timedelta(hours=2))
|
||||||
|
|
||||||
token.with_grants(
|
token.with_grants(
|
||||||
api.VideoGrants(
|
api.VideoGrants(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ port: 7880
|
||||||
rtc:
|
rtc:
|
||||||
tcp_port: 7881
|
tcp_port: 7881
|
||||||
port_range_start: 51000
|
port_range_start: 51000
|
||||||
port_range_end: 51100
|
port_range_end: 52000
|
||||||
use_external_ip: false
|
use_external_ip: false
|
||||||
# node_ip: "94.183.170.121"
|
# node_ip: "94.183.170.121"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,145 @@ def test_group_routes_are_namespaced():
|
||||||
}
|
}
|
||||||
|
|
||||||
assert ("/groups/", "POST") in route_map
|
assert ("/groups/", "POST") in route_map
|
||||||
|
assert ("/groups/{group_id}/members/{user_id}", "DELETE") in route_map
|
||||||
assert ("/admin/groups/", "POST") in route_map
|
assert ("/admin/groups/", "POST") in route_map
|
||||||
assert ("/admin/groups/", "GET") in route_map
|
assert ("/admin/groups/", "GET") in route_map
|
||||||
assert ("/admin/groups/{group_id}/members", "GET") in route_map
|
assert ("/admin/groups/{group_id}/members", "GET") in route_map
|
||||||
assert ("/admin/groups/{group_id}/members", "POST") in route_map
|
assert ("/admin/groups/{group_id}/members", "POST") in route_map
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_allows_manager_to_remove_member(monkeypatch):
|
||||||
|
db = object()
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
manager_id = uuid.uuid4()
|
||||||
|
member_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=uuid.uuid4())
|
||||||
|
removed = AsyncMock()
|
||||||
|
|
||||||
|
async def fake_get_group_member(db, requested_group_id, requested_user_id):
|
||||||
|
if requested_user_id == manager_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MANAGER)
|
||||||
|
if requested_user_id == member_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MEMBER)
|
||||||
|
return None
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(service, "get_group_member", fake_get_group_member)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", removed)
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=manager_id, is_admin=False)
|
||||||
|
await service.remove_member_from_group(db, group_id, member_id, requester)
|
||||||
|
|
||||||
|
removed.assert_awaited_once_with(db, group_id, member_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_rejects_non_manager(monkeypatch):
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
requester_id = uuid.uuid4()
|
||||||
|
member_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=uuid.uuid4())
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(
|
||||||
|
service,
|
||||||
|
"get_group_member",
|
||||||
|
AsyncMock(return_value=SimpleNamespace(role=GroupMemberRole.MEMBER)),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", AsyncMock())
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=requester_id, is_admin=False)
|
||||||
|
|
||||||
|
with pytest.raises(PermissionError, match="دسترسی لازم را ندارید"):
|
||||||
|
await service.remove_member_from_group(object(), group_id, member_id, requester)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_rejects_owner_removal(monkeypatch):
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
manager_id = uuid.uuid4()
|
||||||
|
owner_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=owner_id)
|
||||||
|
|
||||||
|
async def fake_get_group_member(db, requested_group_id, requested_user_id):
|
||||||
|
if requested_user_id == manager_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MANAGER)
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MEMBER)
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(service, "get_group_member", fake_get_group_member)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", AsyncMock())
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=manager_id, is_admin=False)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="حذف سازنده گروه مجاز نیست"):
|
||||||
|
await service.remove_member_from_group(object(), group_id, owner_id, requester)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_rejects_missing_target_membership(monkeypatch):
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
manager_id = uuid.uuid4()
|
||||||
|
member_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=uuid.uuid4())
|
||||||
|
|
||||||
|
async def fake_get_group_member(db, requested_group_id, requested_user_id):
|
||||||
|
if requested_user_id == manager_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MANAGER)
|
||||||
|
return None
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(service, "get_group_member", fake_get_group_member)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", AsyncMock())
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=manager_id, is_admin=False)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="کاربر عضو این گروه نیست"):
|
||||||
|
await service.remove_member_from_group(object(), group_id, member_id, requester)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_rejects_manager_target_for_non_admin(monkeypatch):
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
manager_id = uuid.uuid4()
|
||||||
|
other_manager_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=uuid.uuid4())
|
||||||
|
|
||||||
|
async def fake_get_group_member(db, requested_group_id, requested_user_id):
|
||||||
|
if requested_user_id == manager_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MANAGER)
|
||||||
|
if requested_user_id == other_manager_id:
|
||||||
|
return SimpleNamespace(role=GroupMemberRole.MANAGER)
|
||||||
|
return None
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(service, "get_group_member", fake_get_group_member)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", AsyncMock())
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=manager_id, is_admin=False)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="حذف مدیر گروه مجاز نیست"):
|
||||||
|
await service.remove_member_from_group(object(), group_id, other_manager_id, requester)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_remove_member_from_group_allows_admin_to_remove_manager(monkeypatch):
|
||||||
|
db = object()
|
||||||
|
group_id = uuid.uuid4()
|
||||||
|
target_manager_id = uuid.uuid4()
|
||||||
|
group = SimpleNamespace(owner_id=uuid.uuid4())
|
||||||
|
removed = AsyncMock()
|
||||||
|
|
||||||
|
monkeypatch.setattr(service, "get_group_by_id", AsyncMock(return_value=group))
|
||||||
|
monkeypatch.setattr(
|
||||||
|
service,
|
||||||
|
"get_group_member",
|
||||||
|
AsyncMock(return_value=SimpleNamespace(role=GroupMemberRole.MANAGER)),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(service, "delete_group_member", removed)
|
||||||
|
|
||||||
|
requester = SimpleNamespace(id=uuid.uuid4(), is_admin=True)
|
||||||
|
await service.remove_member_from_group(db, group_id, target_manager_id, requester)
|
||||||
|
|
||||||
|
removed.assert_awaited_once_with(db, group_id, target_manager_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user