def join(self, request, token): token = token.upper() student = get_object_or_404(Student, access_token=token) lesson = Room.objects.filter(group=student.group).last() if not lesson: return HttpResponseRedirect(redirect_to=limbo_url(token)) bbb_api = BigBlueButtonAPI(lesson.server_node.hostname, lesson.server_node.api_secret) if not bbb_api.is_meeting_running(lesson.bbb_meeting_id): # TODO - soft delete? lesson.delete() return HttpResponseRedirect(redirect_to=limbo_url(token)) try: # TODO - where do I take pass from? redirect_url = bbb_api.get_join_url( meeting_id=lesson.bbb_meeting_id, password=lesson.attendee_secret, join_as=student.display_name, assing_user_id=student.uuid, ) except: # TODO - too broad return HttpResponseRedirect(redirect_to=limbo_url(token)) return HttpResponseRedirect(redirect_to=redirect_url)
def start_lesson(group, moderator): """""" room = get_group_active_meeting(group) # group does not have running meeting, create one if not room: server = ServerNode.assign_server(group=group) room, _ = Room.objects.get_or_create(server_node=server, group=group) server = room.server_node api = BigBlueButtonAPI(server.hostname, server.api_secret) try: bbb_room = api.create_room( meeting_id=room.bbb_meeting_id, attendee_secret=User.objects.make_random_password(), moderator_secret=User.objects.make_random_password(), ) room.attendee_secret = bbb_room.attendeePW room.moderator_secret = bbb_room.moderatorPW room.save() except RoomAlreadyExistsError: pass # Connect to room redirect_url = api.get_join_url( meeting_id=room.bbb_meeting_id, password=room.moderator_secret, join_as=moderator.display_name, assing_user_id=moderator.uuid, ) return redirect_url
def _start_lesson(group, moderator): room = _get_or_create_room(group) server = room.server_node api = BigBlueButtonAPI(server.hostname, server.api_secret) try: bbb_room = api.create_room( meeting_id=room.bbb_meeting_id, attendee_secret=User.objects.make_random_password(), moderator_secret=User.objects.make_random_password(), ) room.attendee_secret = bbb_room.attendeePW room.moderator_secret = bbb_room.moderatorPW room.save() except RoomAlreadyExistsError: pass # Connect to room redirect_url = api.get_join_url( meeting_id=room.bbb_meeting_id, password=room.moderator_secret, # TODO - temporary, until RODO is sorted out join_as='ProwadzÄ…cy', # join_as=moderator.display_name, assing_user_id=moderator.uuid, ) logger.debug(f'Mod {moderator.id} start_lesson room {room.id} for {group.display_name}@{server.hostname}') return redirect_url
def get_group_active_meeting(group): room = Room.objects.filter(group=group).last() if room: server = room.server_node api = BigBlueButtonAPI(server.hostname, server.api_secret) if api.is_meeting_running(room.bbb_meeting_id): return room return None
def get_student_access_url(token): """ Get access url for student, perform checks. :param token: Student access token :return: redirect url for student or None """ # Token & Student try: student = Student.objects.get(access_token__iexact=token) student.last_accessed = now() student.save() except Student.DoesNotExist: logger.warning(f"Token {token} has no associated student.") return None # Get meeting details try: lesson = Room.objects.filter(group=student.group).latest('id') bbb_api = BigBlueButtonAPI(lesson.server_node.hostname, lesson.server_node.api_secret) room_details, attendees = bbb_api.get_meeting_info(lesson.bbb_meeting_id) except Room.DoesNotExist: logger.warning(f"Token {token} has no associated lesson.") return None except BBBRequestFailed as e: logger.error(f"Unable to fetch meeting {lesson.bbb_meeting_id} info: {e}") return None # Check: meeeting not running, remove from pool if room_details.running != apibool(True): logger.error(f"Meeting {lesson.bbb_meeting_id} is not running.") return None # Check: max sessions for token student_sessions = [a.userID for a in attendees].count(student.uuid) if student_sessions >= settings.MAX_STUDENT_TOKEN_SESSIONS: logger.warning( f"Student {student.uuid} token {token} has max number of active sessions.") return None try: return bbb_api.get_join_url( meeting_id=lesson.bbb_meeting_id, password=lesson.attendee_secret, join_as=student.display_name, assing_user_id=student.uuid, ) except BBBRequestFailed as e: logger.error(f"Unable to fetch redirect url {lesson.bbb_meeting_id}: {e}") return None
def register_server_node(cls, hostname, api_secret, display_name=None): # Verify hostname from allowed domain if not hostname.endswith(settings.BBB_DOMAIN_ALLOWED): return api = BigBlueButtonAPI(hostname, api_secret) if api.check_connection(): try: server_node = ServerNode.objects.get(hostname=hostname) except ServerNode.DoesNotExist: server_node = ServerNode(hostname=hostname, display_name=display_name or hostname) server_node.api_secret = api_secret server_node.save() return server_node
def _get_or_create_room(group): """"Returns active room for a group or assigns new one.""" room = group.last_meeting_room() # Room already exists, got to probe it if room: server = room.server_node api = BigBlueButtonAPI(server.hostname, server.api_secret) if api.is_meeting_running(room.bbb_meeting_id): logger.info(f'Meeting for group {group} already in progress.') return room else: # Room leftover, clean it from BBB and let assign new logger.info(f'Cleaning leftover room for group {group}') Room.objects.filter(id=room.id).delete() room = None # Room not found or not active, assign new from refreshed pool if not room: server = ServerNode.assign_server(group=group) room, _ = Room.objects.get_or_create(server_node=server, group=group) return room
def test_is_meeting_running_with_unreachable_server_not_rises(self): """Unmocked, check behavior with non-existent server.""" api = BigBlueButtonAPI(hostname='this.hostname.is.totally.fake', api_secret='dddd') self.assertFalse(api.is_meeting_running('fake_meeting_id'))
def test_check_create_room_with_unreachable_server_rises(self): """Unmocked, check behavior with non-existent server.""" api = BigBlueButtonAPI(hostname='this.hostname.is.totally.fake', api_secret='dddd') self.assertRaises(BBBServerUnreachable, api.create_room, meeting_id='abc', attendee_secret='def', moderator_secret='ghi')
def test_check_connection_with_unreachable_server_not_rises(self): """Unmocked, check behavior with non-existent server.""" api = BigBlueButtonAPI(hostname='this.hostname.is.totally.fake', api_secret='dddd') self.assertFalse(api.check_connection())