13 KiB
راهنمای گرفتن توکن و ورود کلاینت به کلاسهای plugNmeet
این راهنما خلاصه میکند که برای سناریوی استاد/دانشجو چگونه از سرویس plugNmeet توکن بگیریم و کلاینت فرانتاند (client/) با آن وارد کلاس شود.
پیشنیازها
- آدرس سرویس:
window.PLUG_N_MEET_SERVER_URL = "https://meet.newhorizonco.uk"(درconfig.js). api_keyوsecretاز فایل پیکربندی بکاند (services/plugnmeet-server/config.yaml).- بدنهٔ درخواستها باید با پروتکل JSON متناظر با پیامهای پروتوباف (
plugnmeet-protocol) ارسال شود؛ سرور طبقHandleAuthHeaderCheckهدرهای امنیتی را بررسی میکند.
گام ۱: ایجاد یا فعال بودن اتاق
API Endpoint برای Django Backend:
POST /api/courses/<course-slug>/online/room/create/
بدنه درخواست از فرانت به Django:
{
"subject": "کلاس جبر فصل ۱" // اختیاری - عنوان روم
}
⚠️ نکات مهم:
- فرانت نباید
metadataارسال کند! - بکاند Django (در
apps/course/views/live_session.py) بهطور خودکار تنظیمات امنیتی را اعمال میکند - این تضمین میکند که تنظیمات امنیتی بهصورت متمرکز و یکسان اعمال شود
بدنه درخواست از Django به PlugNMeet (خودکار):
بکاند Django این بدنه را خودش به PlugNMeet ارسال میکند:
{
"room_id": "algebra-1402",
"metadata": {
"room_title": "کلاس جبر فصل ۱",
"default_lock_settings": {
"lock_microphone": true, // 🔒 قفل - فقط میزبان میتواند باز کند
"lock_webcam": true, // 🔒 قفل - فقط میزبان میتواند باز کند
"lock_screen_sharing": true // 🔒 قفل - فقط میزبان میتواند باز کند
},
"room_features": {
"mute_on_start": true, // 🔇 همه با میک خاموش وارد میشوند
"waiting_room_features": {
"is_active": false
}
}
}
}
چرا بکاند این کار را میکند؟
- ✅ امنیت متمرکز: تنظیمات امنیتی در یک جا کنترل میشود
- ✅ جلوگیری از دستکاری: فرانت نمیتواند تنظیمات را تغییر دهد
- ✅ یکپارچگی: همه کلاسها با تنظیمات یکسان ساخته میشوند
- 🔒 طبق تابع
AssignLockSettingsToUserدرpkg/models/user_lock.goاین مقادیر برای کاربران غیر-admin اعمال میشود
گام ۲: گرفتن توکن ورود
API Endpoint برای Django Backend:
POST /api/courses/online/room/token/
درخواست از فرانت به Django:
Headers:
Authorization: Token <USER_TOKEN>
Content-Type: application/json
Body:
{
"course_slug": "algebra-10"
}
⚠️ نکات مهم:
- فرانت فقط
course_slugارسال میکند! - بکاند Django از
Authorizationheader کاربر را شناسایی میکند - بکاند خودش live session فعال دوره را پیدا میکند:
# 1. پیدا کردن دوره course = Course.objects.get(slug=course_slug) # 2. پیدا کردن live session فعال session = CourseLiveSession.objects.get( course=course, ended_at__isnull=True # session هایی که هنوز به پایان نرسیدهاند ) # 3. گرفتن room_id room_id = session.room_id - بکاند خودش همه اطلاعات کاربر را میسازد:
user_idازrequest.usernameازuser.get_full_name()یاuser.emailis_adminازuser.can_manage_course(course)profilePicازuser.avatarlock_settingsبرای غیر-admin
بدنه درخواست از Django به PlugNMeet (خودکار):
بکاند Django این payload را خودش میسازد و به PlugNMeet میفرستد:
برای استاد:
{
"room_id": "algebra-1402",
"user_info": {
"user_id": "10", // 🔐 از request.user
"name": "استاد نمونه", // 🔐 از user.get_full_name()
"is_admin": true, // 🔐 از user.can_manage_course()
"user_metadata": {
"is_hidden": false,
"profilePic": "https://..." // 🔐 از user.avatar
}
}
}
برای دانشجو:
{
"room_id": "algebra-1402",
"user_info": {
"user_id": "27", // 🔐 از request.user
"name": "دانشجو نمونه", // 🔐 از user.get_full_name()
"is_admin": false, // 🔐 از user.can_manage_course()
"user_metadata": {
"profilePic": "https://...", // 🔐 از user.avatar
"lock_settings": { // 🔒 خودکار برای غیر-admin
"lock_microphone": true,
"lock_screen_sharing": true,
"lock_webcam": true
}
}
}
}
نحوه کار بکاند Django:
# 1. شناسایی کاربر از token
user = request.user # از Authorization header
# 2. پیدا کردن دوره و session فعال
course = Course.objects.get(slug=course_slug)
session = CourseLiveSession.objects.get(course=course, ended_at__isnull=True)
room_id = session.room_id
# 3. تشخیص نقش
is_admin = user.can_manage_course(course) # استاد یا مالک دوره
# 4. ساخت user_info
user_info = {
'user_id': str(user.id),
'name': user.get_full_name() or user.email,
'is_admin': is_admin,
}
# 4. اضافه کردن profilePic
profile_pic = request.build_absolute_uri(user.avatar.url)
user_metadata['profilePic'] = profile_pic
# 5. اضافه کردن lock_settings برای غیر-admin
if not is_admin:
user_metadata['lock_settings'] = {
'lock_microphone': True,
'lock_screen_sharing': True,
'lock_webcam': True,
}
ارسال به PlugNMeet:
بکاند Django با هدرهای امنیتی به PlugNMeet ارسال میکند:
API-KEY: از settingsHASH-SIGNATURE:HMAC_SHA256(body, secret)- این توکن JWT اختصاصی plugNmeet است که در
GeneratePNMJoinTokenساخته میشود is_admin: trueباعث میشود درGetPNMJoinTokenکاربر به عنوان presenter با تمام دسترسیها ثبت شودlock_settingsباعث میشود در فرانتاند PlugNMeet دکمههای میکروفون/وبکم غیرفعال شوند
پاسخ Django به فرانت:
{
"room_id": "algebra-1402",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"plugnmeet": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires": 300,
...
}
}
فرانت با این token میتواند کاربر را به PlugNMeet وارد کند:
https://meet.newhorizonco.uk/?access_token=<TOKEN>
گام ۳: ورود کلاینت با توکن
۱. توکن را در URL یا کوکی قرار دهید؛ کلاینت مقدار را از access_token در کوئریاسترینگ یا از کوکی pnm_access_token میخواند (getAccessToken در client/src/helpers/utils.ts).
۲. آدرس ورود: https://meet.newhorizonco.uk/?access_token=<TOKEN>.
۳. اپلیکیشن React موجود در client/src/components/app/index.tsx پس از بارگذاری:
- درخواست
POST /api/verifyTokenرا با هدرAuthorization: <TOKEN>میفرستد (HandleVerifyToken). - اگر توکن معتبر باشد، لیست آدرسهای NATS و موضوعات لازم را میگیرد و اتصال را آغاز میکند (
startNatsConn). ۴. پس از اتصال، وضعیت کاربر و اتاق در Redux ذخیره میشود (sessionSlice). اگر کاربر ادمین باشد، تمام امکانات بدون محدودیت فعال است؛ در غیر این صورت مقدارهایlock_settingsتعیین میکنند چه دکمههایی فعال باشند.
کنترل حالت صحبت/شنیدن برای استاد و دانشجو
استاد (Moderator/Host):
- ✅ در توکن
is_admin: trueارسال میشود - ✅ بکاند Django در
apps/course/views/live_session.pyاین را تشخیص میدهد:is_admin = user.can_manage_course(course) # استاد یا مالک دوره - ✅ سرور PlugNMeet در
GetPNMJoinTokenرول presenter را فعال میکند - ✅ هیچ قفلی روی میکروفون، وبکم یا اشتراک صفحه اعمال نمیشود
- 🎤 استاد میتواند بلافاصله صحبت کند و به دانشجو اجازه صحبت دهد
دانشجو (Participant):
- 🔒 در توکن
is_admin: falseارسال میشود - 🔒 بکاند Django خودکار lock_settings را اضافه میکند:
if not is_admin: user_metadata['lock_settings'] = { 'lock_microphone': True, 'lock_screen_sharing': True, 'lock_webcam': True, } - 🔇 دکمههای میکروفون، وبکم و اشتراک صفحه غیرفعال هستند
- 👂 فقط میتواند گوش دهد تا میزبان اجازه دهد
- این منطق در
joinModal.tsxبا متغیرisMicLockپیادهسازی شده است
نحوه دادن اجازه به دانشجو:
- میزبان باید از داخل کلاس از طریق UI کنترل کند
- یا از API
/api/updateLockSettingsیاswitchPresenterاستفاده کند
نکات تکمیلی
توکنها و انقضا:
- توکنها زمان انقضای مفهومی دارند (
client.token_validityدر YAML) - در صورت نزدیک شدن به انقضا، کلاینت خودکار با
REQ_RENEW_PNM_TOKENدرخواست تمدید میدهد
Authorization:
- برای درخواستهای بعدی به
/api/...همان هدرAuthorizationرا ست کنید - کلاینت این کار را در
helpers/api/plugNmeetAPI.tsانجام میدهد
مدیریت دسترسیها:
- اگر میخواهید دانشجو را به صحبتکننده ارتقا دهید:
/api/updateLockSettingsیاswitchPresenter - این کار فقط توسط میزبان امکانپذیر است
🔐 جمعبندی امنیت
❌ چیزهایی که فرانت نباید انجام دهد:
موقع ساخت روم:
- ❌ ارسال
metadata - ❌ ارسال
default_lock_settings - ❌ ارسال
room_features
موقع گرفتن توکن:
- ❌ ارسال
room_id(بکاند خودش از session فعال میگیرد) - ❌ ارسال
user_info - ❌ ارسال
is_admin - ❌ ارسال
lock_settings - ❌ ارسال
user_idیاname
✅ چیزهایی که فرانت فقط ارسال میکند:
موقع ساخت روم:
{
"room_id": "algebra-1402", // اختیاری
"subject": "کلاس جبر" // اختیاری
}
موقع گرفتن توکن:
{
"course_slug": "algebra-10" // فقط این!
}
Authorization: Token <USER_TOKEN>در header
✅ چیزهایی که بکاند Django خودش انجام میدهد:
برای همه درخواستها:
- ✅ شناسایی کاربر از
Authorizationheader - ✅ بررسی دسترسی با
user.can_manage_course()یاParticipant.objects.filter()
موقع ساخت روم:
- ✅ تعیین
default_lock_settings(همهtrue) - ✅ تعیین
room_features.mute_on_start: true - ✅ ساخت
metadataکامل برای PlugNMeet
موقع گرفتن توکن:
- ✅ پیدا کردن live session فعال از
course_slug - ✅ گرفتن
room_idاز session - ✅ ساخت
user_idازrequest.user.id - ✅ ساخت
nameازuser.get_full_name()یاuser.email - ✅ تشخیص
is_adminازuser.can_manage_course(course) - ✅ گرفتن
profilePicازuser.avatar - ✅ اضافه کردن
lock_settingsبرای غیر-admin - ✅ ساخت
user_infoکامل برای PlugNMeet
نتیجه:
- 🔒 امنیت کامل: فرانت نمیتواند هیچ تنظیمات امنیتی را دستکاری کند
- ✅ متمرکز: همه logic در بکاند Django است
- 🎯 ساده: فرانت فقط
course_slugوAuthorizationheader ارسال میکند - 🔐 قابل کنترل: بکاند تعیین میکند کدام session فعال است