예제 #1
0
    def set_course(self, message):
        try:
            user = self.handler.user

            if user.status != 'seat':
                return

            # Load Course
            course = yield Course.get(message['course_id'])
            self.handler.course = course

            # User Assign Course
            yield user.assign_course(course.id)

            self.pub_subs['w'].send_message(
                {'type': 'studentSetup.course.set.ok'})

        except KeyError:
            if 'course_id' not in message:
                self.handler.send_malformed_message_error(message)
            else:
                raise

        except NoObjectReturnedFromDB:
            self.handler.send_malformed_message_error(message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(message)
            else:
                raise
예제 #2
0
    def set_course(self, message):
        try:
            user = self.handler.user

            if user.status != 'seat':
                return

            # Load Course
            course = yield Course.get(message['course_id'])
            self.handler.course = course

            # User Assign Course
            yield user.assign_course(course.id)

            self.pub_subs['w'].send_message(
                {'type': 'studentSetup.course.set.ok'})

        except KeyError:
            if 'course_id' not in message:
                self.handler.send_malformed_message_error(
                    message)
            else:
                raise

        except NoObjectReturnedFromDB:
            self.handler.send_malformed_message_error(
                message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(
                    message)
            else:
                raise
예제 #3
0
    def create_course(self, message):
        try:
            course_name = xhtml_escape(message['name'])

            if not re.search('\S', course_name):
                self.pub_subs['w'].send_message({
                    'type': 'createCourseResult',
                    'result': 'emptyName'
                })
                return

            course = yield Course.create(self.handler.user, course_name)

            self.pub_subs['w'].send_message({
                'type': 'createCourseResult',
                'result': 'ok',
                'course_id': course.id
            })

        except KeyError:
            self.handler.send_malformed_message_error(message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(message)

        except DuplicateKeyError:
            self.pub_subs['w'].send_message({
                'type': 'createCourseResult',
                'result': 'duplicate'
            })
예제 #4
0
    def create_course(self, message):
        try:
            course_name = xhtml_escape(message['name'])

            if not re.search('\S', course_name):
                self.pub_subs['w'].send_message(
                    {'type': 'createCourseResult',
                     'result': 'emptyName'})
                return

            course = yield Course.create(
                self.handler.user, course_name)

            self.pub_subs['w'].send_message(
                {
                    'type': 'createCourseResult',
                    'result': 'ok',
                    'course_id': course.id
                }
            )

        except KeyError:
            self.handler.send_malformed_message_error(
                message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(
                    message)

        except DuplicateKeyError:
            self.pub_subs['w'].send_message(
                {'type': 'createCourseResult',
                 'result': 'duplicate'})
예제 #5
0
    def assign_course_to_current_room(self, message):
        try:
            user = self.handler.user

            if user.status != 'room':
                return

            # Load Course
            course = yield Course.get(message['course_id'])
            self.handler.course = course

            # Room Deasign Course
            if user.course_id is not None:
                self.handler.room.deassign_course(
                    user.course_id)

            # Room Assign Course
            room = yield self.handler.room_code.room
            yield room.assign_course(course.id)

            # User Assign Course
            yield user.assign_course(course.id)

            self.course_assignment_source = True
            """This variable identifies the source of the
            ``course.assignment.ok`` message."""

            self.pub_subs['d'].send_message(
                {
                    'type': self.handler.user_msg_type,
                    'content': {
                        'type': 'course.assignment.ok'
                    }
                }
            )

        except KeyError:
            if 'course_id' not in message:
                self.handler.send_malformed_message_error(
                    message)
            else:
                raise

        except NoObjectReturnedFromDB:
            self.handler.send_malformed_message_error(
                message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(
                    message)

            elif not hasattr(self.handler, 'room_code') or \
                    self.handler.room_code is None:
                self.handler.send_room_not_loaded_error(
                    message)

            else:
                raise
예제 #6
0
    def sync_course_id_and_forward_to_client(self, message):
        if not (hasattr(self, 'course_assignment_source')
                and self.course_assignment_source):

            yield self.handler.user.sync('course_id')
            course_id = self.handler.user.course_id

            if course_id is not None:
                self.handler.course = yield Course.get(course_id)

        self.pub_subs['w'].send_message({'type': 'course.assignment.ok'})
예제 #7
0
    def assign_course_to_current_room(self, message):
        try:
            user = self.handler.user

            if user.status != 'room':
                return

            # Load Course
            course = yield Course.get(message['course_id'])
            self.handler.course = course

            # Room Deasign Course
            if user.course_id is not None:
                self.handler.room.deassign_course(user.course_id)

            # Room Assign Course
            room = yield self.handler.room_code.room
            yield room.assign_course(course.id)

            # User Assign Course
            yield user.assign_course(course.id)

            self.course_assignment_source = True
            """This variable identifies the source of the
            ``course.assignment.ok`` message."""

            self.pub_subs['d'].send_message({
                'type': self.handler.user_msg_type,
                'content': {
                    'type': 'course.assignment.ok'
                }
            })

        except KeyError:
            if 'course_id' not in message:
                self.handler.send_malformed_message_error(message)
            else:
                raise

        except NoObjectReturnedFromDB:
            self.handler.send_malformed_message_error(message)

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(message)

            elif not hasattr(self.handler, 'room_code') or \
                    self.handler.room_code is None:
                self.handler.send_room_not_loaded_error(message)

            else:
                raise
예제 #8
0
    def sync_course_id_and_forward_to_client(self, message):
        if not (hasattr(self, 'course_assignment_source')
                and self.course_assignment_source):

            yield self.handler.user.sync('course_id')
            course_id = self.handler.user.course_id

            if course_id is not None:
                self.handler.course = yield Course.get(
                    course_id)

        self.pub_subs['w'].send_message(
            {'type': 'course.assignment.ok'})
예제 #9
0
    def send_room_courses(self, message):
        """Send current room's courses to the client.

        This method is subscribed to the
        ``courses.room.get`` message type.

        The ``user_id`` field of each course is replaced by
        the ``owner`` field. The ``owner`` field contains
        the name of the user, instead of it's ID.

        :param dict message:
            The client's message that executed this method.

        .. todo::
            *   To get the user's names, only one query
                should be made.
                Like: ``User.get_names(id_list)``
        """
        try:
            courses = yield Course.get_courses_from_ids(
                self.handler.room.courses)

            ids = {c['user_id'] for c in courses}
            names = yield {
                id_: User.get_name(id_) for id_ in ids}

            for course in courses:
                course['owner'] = names[
                    course['user_id']
                ]
                del course['user_id']

            self.pub_subs['w'].send_message(
                {'type': 'courses',
                 'courses': courses})

        except AttributeError:
            if not hasattr(self.handler, 'room') or \
                    self.handler.room is None:
                self.handler.send_room_not_loaded_error(
                    message)

            elif not hasattr(self.handler.room, 'courses'):
                """This should never happen again :P."""
                raise

            else:
                raise
예제 #10
0
    def send_room_courses(self, message):
        """Send current room's courses to the client.

        This method is subscribed to the
        ``courses.room.get`` message type.

        The ``user_id`` field of each course is replaced by
        the ``owner`` field. The ``owner`` field contains
        the name of the user, instead of it's ID.

        :param dict message:
            The client's message that executed this method.

        .. todo::
            *   To get the user's names, only one query
                should be made.
                Like: ``User.get_names(id_list)``
        """
        try:
            courses = yield Course.get_courses_from_ids(
                self.handler.room.courses)

            ids = {c['user_id'] for c in courses}
            names = yield {id_: User.get_name(id_) for id_ in ids}

            for course in courses:
                course['owner'] = names[course['user_id']]
                del course['user_id']

            self.pub_subs['w'].send_message({
                'type': 'courses',
                'courses': courses
            })

        except AttributeError:
            if not hasattr(self.handler, 'room') or \
                    self.handler.room is None:
                self.handler.send_room_not_loaded_error(message)

            elif not hasattr(self.handler.room, 'courses'):
                """This should never happen again :P."""
                raise

            else:
                raise
예제 #11
0
    def send_user_courses(self, message):
        """Send current user's courses to the client.

        This method is subscribed to the
        ``courses.user.get`` message type.

        :param dict message:
            The client's message that executed this method.
        """
        try:
            courses = yield Course.get_user_courses(self.handler.user)

            self.pub_subs['w'].send_message({
                'type': 'courses',
                'courses': courses
            })

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(message)

            else:
                raise
예제 #12
0
    def send_user_courses(self, message):
        """Send current user's courses to the client.

        This method is subscribed to the
        ``courses.user.get`` message type.

        :param dict message:
            The client's message that executed this method.
        """
        try:
            courses = yield Course.get_user_courses(
                self.handler.user)

            self.pub_subs['w'].send_message(
                {'type': 'courses',
                 'courses': courses})

        except AttributeError:
            if not hasattr(self.handler, 'user'):
                self.handler.send_user_not_loaded_error(
                    message)

            else:
                raise
예제 #13
0
    def startSession(self, message):
        """Start a user session

        .. todo::
            *   Add a variable that indicates the last stage
                that was executed successfully. So that the
                finally clause can clean the mess properly.
        """
        try:
            yield self.load_user(message['token'])
            self.sub_to_user_messages()
            code_type, room_name, seat_id = \
                yield self.load_room_code(
                    message['room_code'])

            user = self.handler.user
            room_code = self.handler.room_code
            room = self.handler.room

            course_id = user.course_id
            has_course = course_id is not None

            was_none = (user.status == 'none')
            was_student = (user.status == 'seat')
            was_teacher = (user.status == 'room')

            is_none = (code_type == 'none')
            is_student = (code_type == 'seat')
            is_teacher = (code_type == 'room')

            distinct_room = not (
                room_name is None or
                user.room_name is None or
                room_name == user.room_name
            )

            same_seat = (seat_id == user.seat_id) and \
                not distinct_room

            transition_data = (
                has_course, was_none, was_student,
                was_teacher, is_none, is_student,
                is_teacher, distinct_room
            )

            # Redirect to Teacher View
            if self.should_run_redirect_to_teacher_view(
                    *transition_data):
                self.redirect_to_teacher_view(
                    user.room_code, message)
                # The rest of the code is not executed.
                return

            # Room Deassign Course
            '''This should always run before "User Deassign
            Course"'''
            if self.should_run_room_deassign_course(
                    *transition_data):
                if distinct_room:
                    r = yield Room.get(user.room_name)
                else:
                    r = room

                yield r.deassign_course(course_id)

            # User Deassign Course
            if self.should_run_user_deassign_course(
                    *transition_data):
                yield user.deassign_course()

            # Logout Other Instances
            if self.should_run_logout_other_instances(
                    *transition_data):
                self.block_logout = True
                self.pub_subs['d'].send_message(
                    {
                        'type': self.handler.user_msg_type,
                        'content': {
                            'type': 'logout',
                            'reason': 'exclusiveLogin',
                            'user_state_at_exclusive_login':
                                user._data,
                            'dont_leave_seat': same_seat,
                        }
                    }
                )

            # Use Seat
            if self.should_run_use_seat(*transition_data) \
                    and (not same_seat or
                         user.instances == 0):
                yield room.use_seat(room_code.seat_id)

            # Load Course
            if self.should_run_load_course(
                    *transition_data):
                self.handler.course = yield Course.get(
                    course_id)

            # Increase Instances
            yield self.handler.user.increase_instances()

            yield self.handler.user.store_dict(
                {
                    'status': code_type,
                    'room_code': message['room_code'],
                    'room_name': room_name,
                    'seat_id': seat_id,
                }
            )

        except jwt.InvalidTokenError:
            self.handler.logout_and_close('invalidToken')

        except ConditionNotMetError:
            self.send_session_start_error(
                message,
                'Es probable que este error se daba a que '
                'el asiento que desea registrar ya está '
                'usado.'
            )

        except OperationFailure:
            self.send_session_start_error(
                message,
                'Una operación de la base de datos ha '
                'fallado.'
            )

        except KeyError:
            keys_in_message = all(
                map(
                    lambda k: k in message,
                    ('token', 'room_code')
                )
            )
            if not keys_in_message:
                self.handler.send_malformed_message_error(
                    message)
            else:
                raise

        else:
            self.session_start_ok = True

            self.pub_subs['w'].send_message(
                {
                    'type': 'session.start.ok',
                    'code_type': code_type,
                    'course_id': user.course_id
                }
            )

        finally:
            if not self.session_start_ok:
                pass
예제 #14
0
    def startSession(self, message):
        """Start a user session

        .. todo::
            *   Add a variable that indicates the last stage
                that was executed successfully. So that the
                finally clause can clean the mess properly.
        """
        try:
            yield self.load_user(message['token'])
            self.sub_to_user_messages()
            code_type, room_name, seat_id = \
                yield self.load_room_code(
                    message['room_code'])

            user = self.handler.user
            room_code = self.handler.room_code
            room = self.handler.room

            course_id = user.course_id
            has_course = course_id is not None

            was_none = (user.status == 'none')
            was_student = (user.status == 'seat')
            was_teacher = (user.status == 'room')

            is_none = (code_type == 'none')
            is_student = (code_type == 'seat')
            is_teacher = (code_type == 'room')

            distinct_room = not (room_name is None or user.room_name is None
                                 or room_name == user.room_name)

            same_seat = (seat_id == user.seat_id) and \
                not distinct_room

            transition_data = (has_course, was_none, was_student, was_teacher,
                               is_none, is_student, is_teacher, distinct_room)

            # Redirect to Teacher View
            if self.should_run_redirect_to_teacher_view(*transition_data):
                self.redirect_to_teacher_view(user.room_code, message)
                # The rest of the code is not executed.
                return

            # Room Deassign Course
            '''This should always run before "User Deassign
            Course"'''
            if self.should_run_room_deassign_course(*transition_data):
                if distinct_room:
                    r = yield Room.get(user.room_name)
                else:
                    r = room

                yield r.deassign_course(course_id)

            # User Deassign Course
            if self.should_run_user_deassign_course(*transition_data):
                yield user.deassign_course()

            # Logout Other Instances
            if self.should_run_logout_other_instances(*transition_data):
                self.block_logout = True
                self.pub_subs['d'].send_message({
                    'type': self.handler.user_msg_type,
                    'content': {
                        'type': 'logout',
                        'reason': 'exclusiveLogin',
                        'user_state_at_exclusive_login': user._data,
                        'dont_leave_seat': same_seat,
                    }
                })

            # Use Seat
            if self.should_run_use_seat(*transition_data) \
                    and (not same_seat or
                         user.instances == 0):
                yield room.use_seat(room_code.seat_id)

            # Load Course
            if self.should_run_load_course(*transition_data):
                self.handler.course = yield Course.get(course_id)

            # Increase Instances
            yield self.handler.user.increase_instances()

            yield self.handler.user.store_dict({
                'status':
                code_type,
                'room_code':
                message['room_code'],
                'room_name':
                room_name,
                'seat_id':
                seat_id,
            })

        except jwt.InvalidTokenError:
            self.handler.logout_and_close('invalidToken')

        except ConditionNotMetError:
            self.send_session_start_error(
                message, 'Es probable que este error se daba a que '
                'el asiento que desea registrar ya está '
                'usado.')

        except OperationFailure:
            self.send_session_start_error(
                message, 'Una operación de la base de datos ha '
                'fallado.')

        except KeyError:
            keys_in_message = all(
                map(lambda k: k in message, ('token', 'room_code')))
            if not keys_in_message:
                self.handler.send_malformed_message_error(message)
            else:
                raise

        else:
            self.session_start_ok = True

            self.pub_subs['w'].send_message({
                'type': 'session.start.ok',
                'code_type': code_type,
                'course_id': user.course_id
            })

        finally:
            if not self.session_start_ok:
                pass