بنقرة واحدة
bedrud-api-rooms
Room endpoints — CRUD, join, moderation, presence, chat upload, stage stubs, recording.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Room endpoints — CRUD, join, moderation, presence, chat upload, stage stubs, recording.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Admin endpoints — users, rooms, queue, settings, invite tokens, webhooks, overview, recordings.
Auth endpoints — JWT flow, local/OAuth/passkey/verify/password-reset/avatar/preferences.
Complete Bedrud API endpoint reference. Dense index of every route, middleware, status code; deep detail in leaf skills.
All DTO definitions, source file index, Swagger reference.
Auth service + middleware — JWT, passkeys, OAuth, session store, rate limiting, recordings gate.
Data layer — GORM models, repository, database init, test utilities, admin DTOs.
| name | bedrud-api-rooms |
| description | Room endpoints — CRUD, join, moderation, presence, chat upload, stage stubs, recording. |
| license | Apache License |
Source of truth: server/internal/server/server.go and server/cmd/server/main.go route registration.
Handlers: server/internal/handlers/room.go, server/internal/handlers/recording_handler.go.
Path prefix rule
/api/room/.../api/rooms/:id/.../api/admin/... (see bedrud-api-admin, not listed here)Auth shorthand
P+EV = Protected() + RequireEmailVerifiedP+EV. Exceptions called out per row.{"error":"<msg>"} unless noted.| Method | Path | Auth / MW | Handler | Req | Res | Status |
|---|---|---|---|---|---|---|
| POST | /api/room/create | P+EV + APIRate | CreateRoom | CreateRoomRequest | room + livekitHost | 200 / 400 / 403 / 409 / 500 |
| POST | /api/room/join | P+EV | JoinRoom | {roomName} | join payload + token | 200 / 403 / 404 / 410 / 500 |
| POST | /api/room/guest-join | GuestRate only | GuestJoinRoom | {roomName, guestName} | guest join payload + token | 200 / 400 / 403 / 404 / 410 |
| POST | /api/room/refresh-token | P+EV + APIRate | RefreshLiveKitToken | {roomName} | {token} | 200 / 400 / 403 / 404 / 410 |
| GET | /api/room/list | P+EV | ListRooms | — | []models.Room (caller’s latest) | 200 |
| GET | /api/room/archived | P+EV | ListArchivedRooms | ?page=&limit= | {rooms[], total, page, limit} | 200 |
| PUT | /api/room/:roomId/settings | P+EV | UpdateSettings | partial settings body | models.Room | 200 / 400 / 403 / 404 |
| DELETE | /api/room/:roomId | P+EV | DeleteRoom | — | {"message":"Room deletion queued"} | 202 / 403 / 404 / 409 / 500 |
| POST | /api/room/:roomId/chat/upload | P+EV + APIRate | UploadChatImage | multipart file | ChatAttachment or queued | 200 / 202 / 400 / 403 / 404 / 413 / 507 |
| GET | /api/room/:roomId/presence | APIRate only (no JWT) | GetRoomPresence | ?countOnly=1 optional | {participants[]} or {count} | 200 / 404 / 500 |
{ name string, maxParticipants int, isPublic bool, mode string, settings RoomSettings }
mode: standard (default) | webinar | broadcastsettings.recordingsAllowed forced true on create.isPersistent stripped; enforces MaxRoomsPerUser (403).MaxParticipantsLimit (settings).c.JSON(...) → HTTP 200 (not 201).{"id":"uuid","name":"xxx-xxxx-xxx","createdBy":"uuid","isActive":true,"isPublic":false,"maxParticipants":20,"settings":{},"livekitHost":"ws://...","mode":"standard"}
{"id":"uuid","name":"room-name","token":"lk-jwt","createdBy":"uuid","adminId":"uuid","isActive":true,"isPublic":false,"maxParticipants":20,"expiresAt":"...","settings":{},"livekitHost":"ws://...","mode":"standard","activeRecordingId":""}
| Condition | Status | Body |
|---|---|---|
| Archived, caller is creator | 200 | {"status":"archived_owned","name","mode","settings"} |
| Inactive, not creator | 410 | {"error":"room is no longer active"} |
| Private + not participant | 403 | private / requires approval |
| Full / banned | 403 | room full / banned |
guest- + short ID identity. Guest name required, max 50, sanitized.GuestLoginEnabled false (403).{id, name, token, adminId, isPublic, livekitHost, activeRecordingId} (no full room dump).{token} only. LK token TTL = livekitTokenTTL.{"id":"...","name":"...","createdAt":"...","deletedAt":"...","recordingCount":0}
Default page size 20 (max 100). Count from recordingRepo.CountByRoom.
{ isPublic *bool, maxParticipants *int, settings *RoomSettings }
isPersistent preserved (admin-only via AdminUpdateRoom).maxParticipants to LiveKit when changed.room_delete (archive, Purge:false — recordings preserved).allowChat required.chat.uploads.maxBytes.MaxUploadBytesPerUser / GlobalDiskThresholdBytes → 507.ChatAttachment {url, mime, size, w, h}.{status:"upload_queued", job_type:"chat_upload_s3", size, mime}.participants (or 404 if countOnly).ListParticipants + avatar lookup for non-guests.?countOnly=1|true → {"count":N} (public only).All P+EV. Path params :roomId + :identity (ask also :action).
| Method | Path | Handler | Authz | Action | Res |
|---|---|---|---|---|---|
| POST | /api/room/:roomId/kick/:identity | KickParticipant | room admin / superadmin | Remove from LK + “kick” system msg | {"status":"success"} |
| POST | /api/room/:roomId/ban/:identity | BanParticipant | room admin / superadmin | Remove + DB ban + “ban” | {"status":"success"} |
| POST | /api/room/:roomId/mute/:identity | MuteParticipant | room admin / superadmin | Mute all audio tracks | {"status":"success"} |
| POST | /api/room/:roomId/video/:identity/off | DisableParticipantVideo | isRoomModerator | Mute camera | {"status":"success"} |
| POST | /api/room/:roomId/screenshare/:identity/stop | StopScreenShare | isRoomModerator | Mute screen + SS-audio | {"status":"success"} |
| POST | /api/room/:roomId/promote/:identity | PromoteParticipant | room admin / superadmin | LK metadata moderator + DB flag | {"status":"success"} / already_moderator |
| POST | /api/room/:roomId/demote/:identity | DemoteParticipant | room admin / superadmin | Remove moderator + clear DB | {"status":"success"} |
| POST | /api/room/:roomId/chat/:identity/block | BlockChat | isRoomModerator | chatBlocked: true metadata | {"status":"success"} |
| POST | /api/room/:roomId/deafen/:identity | DeafenParticipant | isRoomModerator | Targeted “deafen” data msg | {"status":"success"} |
| POST | /api/room/:roomId/undeafen/:identity | UndeafenParticipant | isRoomModerator | Targeted “undeafen” | {"status":"success"} |
| POST | /api/room/:roomId/ask/:identity/:action | AskParticipantAction | isRoomModerator | :action=unmute|camera → ask_* | {"status":"success"} |
| POST | /api/room/:roomId/spotlight/:identity | SpotlightParticipant | isRoomModerator | Broadcast “spotlight” | {"status":"success"} |
| GET | /api/room/:roomId/participant/:identity/info | GetParticipantInfo | self or isRoomModerator | LK identity/tracks | see below |
| GET | /api/room/:roomId/participant/:identity/profile | GetParticipantProfile | caller must be in LK room | name + avatar | {id, name, avatarUrl} |
| POST | /api/room/:roomId/stage/:identity/bring | BringToStage | P+EV (no body logic) | 501 stub | {"error":"not yet implemented"} |
| POST | /api/room/:roomId/stage/:identity/remove | RemoveFromStage | P+EV | 501 stub | {"error":"not yet implemented"} |
isRoomModeratorSuperadmin or room admin (AdminID‖CreatedBy) or DB room_participants.is_moderator for this room. (room_auth.go)
Kick/ban/mute/promote/demote use stricter admin/superadmin only (not promoted room mods).
Common guards: no self-target (400); often cannot target room admin (403).
{"identity":"uuid","name":"John","state":"ACTIVE","joinedAt":1234567890,"tracks":[{"sid":"TR_xxx","type":"AUDIO","source":"MICROPHONE","muted":false}]}
guest-*): LK display name, empty avatarUrl.Handlers + service are implemented (
recording_handler.go,RecordingService, tests). Production routes are currently commented out inserver/internal/server/server.goandcmd/server/main.go(// TODO oncoming feature: recording routes). Not live until uncommented + egress client wired. Paths below = handler contracts / integration-test wiring.
Prefix: /api/rooms/:id/... (plural rooms, param :id = room UUID).
Intended MW (from integration tests): P+EV + RecordingsEnabled(settingsRepo) (+ APIRate on start).
| Method | Path | Handler | Authz | Req | Res | Status |
|---|---|---|---|---|---|---|
| POST | /api/rooms/:id/recording/start | StartRecording | isRoomModerator | — | {id, status:"started", roomId} | 201 / 403 / 404 / 409 / 500 |
| POST | /api/rooms/:id/recording/stop | StopRecording | isRoomModerator | — | {id, status:"processing"} | 200 / 403 / 404 / 500 |
| GET | /api/rooms/:id/recordings | ListRecordings | canViewRoomRecordings (+ creator fallback) | ?page=&limit= | {recordings: RecordingDTO[], total, page, limit} | 200 / 404 |
| GET | /api/rooms/:id/recordings/:rid | GetRecording | view gate / creator | — | RecordingDTO | 200 / 404 |
| GET | /api/rooms/:id/recordings/:rid/wait | WaitRecordingReady | creator or can-view | long-poll ≤15s | `{status:"active" | "failed" |
| DELETE | /api/rooms/:id/recordings | ClearRoomRecordings | room admin / superadmin | — | {message} or 207 partial | 200 / 207 / 403 / 404 |
| DELETE | /api/rooms/:id/recordings/:recordingId | ClearSingleRecording | room admin / superadmin | — | {message:"Recording cleared"} | 200 / 403 / 404 |
Admin-global recording list/bulk-delete live under /api/admin/recordings (also commented) → bedrud-api-admin.
middleware.RecordingsEnabled → SystemSettings.RecordingsEnabled (403 if off)RecordingService.gateRoom → Room.Settings.RecordingsAllowedisRoomModerator; list/get → canViewRoomRecordings (superadmin / owner / active participant; archived → owner+superadmin only; denied as 404 to avoid leaks)pending → started → processing → completed | failed (+ deleting)
{
"id": "uuid",
"recordingType": "composite",
"durationMs": 0,
"fileSize": 0,
"fileUrl": "...",
"status": "completed",
"error": "",
"downloadStatus": "ready",
"roomId": "uuid",
"roomName": "room",
"createdBy": "user-uuid",
"createdAt": "2025-03-15T10:30:00Z"
}
downloadStatus: failed | processing | ready (computed).
Polls every 500ms up to 15s. Returns active once started/processing/completed; failed with error; 408 timeout.
type RoomSettings struct {
AllowChat bool // default true
AllowVideo bool // default true
AllowAudio bool // default true
RequireApproval bool // default false
E2EE bool // default false
IsPersistent bool // superadmin-only via AdminUpdateRoom
RecordingsAllowed bool // create forces true; gate for recording service
}
| Concern | Path |
|---|---|
| Route registration (prod) | server/internal/server/server.go |
| Route registration (dev Air) | server/cmd/server/main.go |
| Room handlers | server/internal/handlers/room.go |
| Moderator helper | server/internal/handlers/room_auth.go |
| Recording handlers | server/internal/handlers/recording_handler.go |
| Recording service | server/internal/services/recording_service.go |
| RecordingsEnabled MW | server/internal/middleware/recordings_enabled.go |
| Models | server/internal/models/room.go, recording.go |
| Chat upload | server/internal/storage/chat_upload.go |
| Room tests | room_*_test.go, recording_handler_test.go |
Admin room list/close/suspend/bulk, admin participant kick/mute, /api/admin/online-count, admin recordings → bedrud-api-admin.
LiveKit webhook (/api/livekit/webhook) → bedrud-realtime / server skill.