def add_new_pricing(request): try: # fields = ['mobile_company', 'mobile_model', 'repairing_part', 'repairing_price', 'repairing_description'] mobile_company = request.data["mobile_company"] mobile_model = request.data["mobile_model"] repairing_part = request.data["repairing_part"] repairing_price = request.data["repairing_price"] repairing_description = request.data["repairing_description"] try: add_price = PricingModel.objects.create( mobile_company=mobile_company, mobile_model=mobile_model, repairing_price=repairing_price, repairing_part=repairing_part, repairing_description=repairing_description) information = {"detail": "A new item has been added successfully"} return Response(information, status=status.HTTP_200_OK) except Exception as e: print(e) except Exception as e: print(e) information = {"detail": "Failed to add new item."} return Response(information, status=status.HTTP_200_OK)
def gitrello_schema(**kwargs): responses = kwargs.pop('responses', {}) if 400 not in responses: responses[400] = Response( schema=ErrorResponseSerializer, description='Given request is invalid for some reason', examples={ 'application/json': { 'error_code': APIRequestValidationException.code, 'error_message': APIRequestValidationException.message, 'error_details': { 'name': [ 'This field is required.', ], 'age': [ 'Not a valid integer', ], } } }) if 401 not in responses: responses[401] = Response( schema=ErrorResponseSerializer, description= 'Authentication credentials were not provided or are incorrect', examples={ 'application/json': { 'error_code': AuthenticationFailedException.code, 'error_message': AuthenticationFailedException.message, 'error_details': { 'error': 'Authentication credentials were not provided.' } }, }) if 403 not in responses: responses[403] = Response( schema=ErrorResponseSerializer, description= 'User is authenticated, but not authorized to perform some action or access some data', examples={ 'application/json': { 'error_code': PermissionDeniedException.code, 'error_message': PermissionDeniedException.message, }, }) security = kwargs.pop('security', None) if security is None: security = [{ 'Bearer': [], }] return swagger_auto_schema( responses=responses, security=security, **kwargs, )
def perform_create(self, serializer): serializer = UsersSerializer(data=self.request.data) if serializer.is_valid(): user = serializer.save() refresh = RefreshToken.for_user(user) data = { 'refresh': str(refresh), 'access': str(refresh.access_token), } data[id] = user.id return Response(data, status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def set_example(example, description='', schema=PlaceholderSerialiser): return Response(examples={"application/json": example}, description=description, schema=schema)
class ClassDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets information for a class.', operation_description='Note : only users with the role `administrator` should be able to access this route.', responses={ 200: Response( description='Class information', schema=Schema( title='ClassResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'class': Schema( title='Class', type=TYPE_OBJECT, properties={ 'name': Schema(type=TYPE_STRING, example='B.001'), 'level': Schema(type=TYPE_STRING, enum=levels), }, required=[ 'name', 'level', ] ), 'total_services': Schema(type=TYPE_INTEGER, example=166), }, required=['status', 'class', 'total_services', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Classes', ] ) def get(self, request, class_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: _class = Class.objects.get(id=class_id) _class = { 'name': _class.name, 'capacity': _class.level, } return RF_Response({'status': 'success', 'class': _class}) except Class.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Updates information for a class.', operation_description='Note : only users with the role `administrator` should be able to access this route.', responses={ 200: Response( description='Data updated', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), }, required=['status', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Invalid level (code=`InvalidLevel`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, example='InvalidLevel', enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Classes', ], request_body=Schema( title='ClassUpdateRequest', type=TYPE_OBJECT, properties={ 'name': Schema(type=TYPE_STRING, example='L3 INFORMATIQUE'), 'level': Schema(type=TYPE_STRING, enum=levels), }, required=['name', 'level', ] ) ) def put(self, request, classroom_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: _class = Class.objects.get(id=classroom_id) data_keys = request.data.keys() if 'name' in data_keys: _class.name = request.data['name'] if 'level' in data_keys: _class.level = request.data['level'] _class.save() return RF_Response({'status': 'success', }) except Classroom.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class StudentViewSet(GenericAPIView, TokenHandlerMixin): serializer_class = StudentSerializer queryset = Student.objects.all() pagination_class = StudentResultSetPagination def get_queryset(self): queryset = super().get_queryset() query = self.request.query_params.get('query', None) if query: if len(query) >= 3: queryset = queryset.filter( Q(first_name__unaccent__icontains=query) | Q(last_name__unaccent__icontains=query) | Q(_class__name__unaccent__icontains=query) ) return queryset.order_by('last_name', 'first_name') @swagger_auto_schema( operation_summary='Returns a paginated list of all students.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' '10 students should be returned per page. At least three characters should be provided ' 'for the search.', responses={ 200: Response( description='A list of all students.', schema=Schema( title='StudentListResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'total': Schema(type=TYPE_INTEGER, description='Total number of students', example=166), 'students': Schema(type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'id': Schema( type=TYPE_INTEGER, example=166), 'first_name': Schema( type=TYPE_STRING, example='John'), 'last_name': Schema( type=TYPE_STRING, example='Doe'), 'class_name': Schema( type=TYPE_STRING, example='L3 INFORMATIQUE'), }, required=['id', 'first_name', 'last_name', 'class_name', ]), ), }, required=['status', 'total', 'students', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Students'], manual_parameters=[ Parameter(name='query', in_=IN_QUERY, type=TYPE_STRING, required=False), ], ) def get(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) result = self.get_paginated_response(serializer.data) response = result.data else: serializer = self.get_serializer(queryset, many=True) response = serializer.data data = { 'status': 'success', 'total': response['count'], 'students': response['results'], } return RF_Response(data) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except NotFound: data = { 'status': 'success', 'total': len(self.get_queryset()), 'teachers': [], } return RF_Response(data) @swagger_auto_schema( operation_summary='Creates a new student.', operation_description='Note : only users with the role `administrator` should be able to access this route. ' 'This should trigger the re-organization of groups.', responses={ 201: Response( description='Student created', schema=Schema( title='AccountCreatedResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'username': Schema(type=TYPE_STRING, example='azure_diamong'), 'password': Schema(type=TYPE_STRING, example='aBcD1234'), }, required=['status', 'username', 'password', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Students'], request_body=Schema( title='StudentCreationRequest', type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'class_id': Schema(type=TYPE_INTEGER, example=166), }, required=['first_name', 'last_name', 'class_id', ] ) ) def post(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) serializer = StudentCreationSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return RF_Response(serializer.data, status=status.HTTP_201_CREATED) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Deletes the given students using their IDs.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'This request should trigger the re-organization of students in the affected groups.', responses={ 200: Response( description='Data deleted', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'success': Schema( type=TYPE_STRING, example='success'), }, required=['success', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Students'], request_body=Schema( title='IDRequest', type=TYPE_ARRAY, items=Schema( type=TYPE_INTEGER, example=166 ) ), ) def delete(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) def delete_student(student_id: int): student = Student.objects.get(id=student_id) student.delete() for post_id in request.data: try: delete_student(post_id) except Student.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) return RF_Response({'status': 'success'}) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class TeacherOccupancyDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets the occupancies of a teacher for the given time period.', operation_description='Note : only users with the role `administrator`, or teachers whose id match the one in ' 'the URL should be able to access this route.', responses={ 200: Response( description='Teacher information', schema=occupancies_schema, ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers', 'role-professor', ], manual_parameters=[ Parameter(name='start', in_=IN_QUERY, type=TYPE_INTEGER, required=True), Parameter(name='end', in_=IN_QUERY, type=TYPE_INTEGER, required=True), Parameter(name='occupancies_per_day', in_=IN_QUERY, type=TYPE_INTEGER, required=True), ] ) def get(self, request, teacher_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: teacher = Teacher.objects.get(id=teacher_id) def get_days() -> list: start_timestamp = request.query_params.get('start', None) end_timestamp = request.query_params.get('end', None) nb_per_day = int(request.query_params.get('occupancies_per_day', 0)) days = [] occ = Occupancy.objects.filter( teacher=teacher, deleted=False ).order_by('start_datetime').annotate(day=Trunc('start_datetime', 'day')) if start_timestamp: occ = occ.filter( start_datetime__gte=datetime.fromtimestamp( int(start_timestamp), tz=timezone(settings.TIME_ZONE) ) ) if end_timestamp: occ = occ.filter( end_datetime__lte=datetime.fromtimestamp( int(end_timestamp), tz=timezone(settings.TIME_ZONE) ) ) for day in (occ[0].day + timedelta(n) for n in range((occ[len(occ) - 1].day - occ[0].day).days + 2)): day_occupancies = occ.filter(start_datetime__day=day.day) if len(day_occupancies) == 0: continue if nb_per_day != 0: day_occupancies = day_occupancies[:nb_per_day] occ_list = [] for o in day_occupancies: event = { 'id': o.id, 'group_name': f'Groupe {o.group_number}', 'subject_name': o.subject.name, 'teacher_name': f'{o.teacher.first_name} {o.teacher.last_name}', 'start': o.start_datetime.timestamp(), 'end': o.end_datetime.timestamp(), 'occupancy_type': o.occupancy_type, 'name': o.name, } if o.subject: event['class_name'] = o.subject._class.name if o.classroom: event['classroom_name'] = o.classroom.name occ_list.append(event) days.append({'date': day.strftime("%d-%m-%Y"), 'occupancies': occ_list}) return days return RF_Response({'status': 'success', 'days': get_days()}) except Teacher.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class TeacherViewSet(GenericAPIView, TokenHandlerMixin): serializer_class = TeacherSerializer queryset = Teacher.objects.all() pagination_class = TeacherResultSetPagination def get_queryset(self): queryset = super().get_queryset() query = self.request.query_params.get('query', None) if query: if len(query) >= 3: queryset = queryset.filter( Q(first_name__unaccent__icontains=query) | Q(last_name__unaccent__icontains=query) | Q(_class__name__unaccent__icontains=query) | Q(phone_number__unaccent__icontains=query) ) return queryset.order_by('last_name', 'first_name') @swagger_auto_schema( operation_summary='Returns a paginated list of all teachers.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n10' ' teachers should be returned per page. If less than three characters are provided ' 'for the query, it will not be applied.\nWarning: the `email` and `phone_number` can be ' 'null.', responses={ 200: Response( description='A list of all teachers.', schema=Schema( title='TeacherListResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'total': Schema(type=TYPE_INTEGER, description='Total number of students', example=166), 'teachers': Schema(type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'id': Schema( type=TYPE_INTEGER, example=166), 'first_name': Schema( type=TYPE_STRING, example='John'), 'last_name': Schema( type=TYPE_STRING, example='Doe'), 'email': Schema( type=TYPE_STRING, example='*****@*****.**'), 'phone_number': Schema( type=TYPE_STRING, example='06 61 66 16 61' ) }, required=['id', 'first_name', 'last_name', 'email', 'phone_number', ]), ), }, required=['status', 'total', 'teachers', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers', ], manual_parameters=[ Parameter(name='query', in_=IN_QUERY, type=TYPE_STRING, required=False), ], ) def get(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) result = self.get_paginated_response(serializer.data) response = result.data else: serializer = self.get_serializer(queryset, many=True) response = serializer.data data = { 'status': 'success', 'total': response['count'], 'teachers': response['results'], } return RF_Response(data) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except NotFound: data = { 'status': 'success', 'total': len(self.get_queryset()), 'teachers': [], } return RF_Response(data) @swagger_auto_schema( operation_summary='Creates a new teacher.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' '`email` and `phone_number` can be null in the request.', responses={ 201: Response( description='Teacher created', schema=Schema( title='AccountCreatedResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'username': Schema(type=TYPE_STRING, example='azure_diamong'), 'password': Schema(type=TYPE_STRING, example='aBcD1234'), }, required=['status', 'username', 'password', ])), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Invalid email (code=`InvalidEmail`)\nInvalid phone number (code=`InvalidPhoneNumber`)\n' 'Invalid rank (code=`InvalidRank`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers'], request_body=Schema( title='StudentCreationRequest', type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'email': Schema(type=TYPE_STRING, example='*****@*****.**'), 'phone_number': Schema(type=TYPE_STRING, example='06 61 66 16 61'), 'rank': Schema(type=TYPE_STRING, enum=ranks), }, required=['first_name', 'last_name', 'email', 'phone_number', 'rank', ] ) ) def post(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) serializer = TeacherCreationSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return RF_Response(serializer.data, status=status.HTTP_201_CREATED) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Deletes the given students using their IDs.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'This request should be denied if the professors are in charge of any subjects. This ' 'should cascade and delete any occupancies they are a part of, and remove them from any ' 'subjects they took part in.', responses={ 200: Response( description='Data deleted', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'success': Schema( type=TYPE_STRING, example='success'), }, required=['success', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='The teacher is still in charge of a subject (code=`TeacherInCharge`).', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers'], request_body=Schema( title='IDRequest', type=TYPE_ARRAY, items=Schema( type=TYPE_INTEGER, example=166 ) ), ) def delete(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) def delete_teacher(student_id: int): student = Teacher.objects.get(id=student_id) student.delete() for post_id in request.data: try: delete_teacher(post_id) except Teacher.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) return RF_Response({'status': 'success'}) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class ProfileNextOccupancy(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets the user\'s next occupancy', operation_description='', responses={ 200: Response( description='Success', schema=Schema( title='', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'occupancy': Schema(type=TYPE_OBJECT, properties={ 'id': Schema(type=TYPE_INTEGER, example=166), 'classroom_name': Schema(type=TYPE_STRING, example='B.001'), 'group_name': Schema(type=TYPE_STRING, example='Groupe 1'), 'subject_name': Schema(type=TYPE_STRING, example='Algorithmique'), 'teacher_name': Schema(type=TYPE_STRING, example='John Doe'), 'start': Schema(type=TYPE_INTEGER, example=1587776227), 'end': Schema(type=TYPE_INTEGER, example=1587776227), 'occupancy_type': Schema(type=TYPE_STRING, enum=occupancy_list), 'class_name': Schema(type=TYPE_STRING, example='L3 INFORMATIQUE'), 'name': Schema(type=TYPE_STRING, example='Algorithmique TP Groupe 1'), }, required=[ 'id', 'group_name', 'subject_name', 'teacher_name', 'start', 'end', 'occupancy_type', 'name', ]), }, required=[ 'status', 'occupancy', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response( description= 'Insufficient rights (administrator) (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=['role-professor', 'role-student']) def get(self, request): try: token = self._get_token(request) if token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) o = Occupancy.objects.filter(start_datetime__gte=datetime.now( tz=timezone(settings.TIME_ZONE))).order_by('start_datetime')[0] event = { 'id': o.id, 'group_name': f'Groupe {o.group_number}', 'subject_name': o.subject.name, 'teacher_name': f'{o.teacher.first_name} {o.teacher.last_name}', 'start': o.start_datetime.timestamp(), 'end': o.end_datetime.timestamp(), 'occupancy_type': o.occupancy_type, 'name': o.name, } if o.subject: event['class_name'] = o.subject._class.name if o.classroom: event['classroom_name'] = o.classroom.name return RF_Response({'status': 'success', 'occupancy': event}) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)
class ProfileICalFeed(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary= 'Gets the URL for the iCal feed for the user\'s calendar', operation_description='', responses={ 200: Response( description='Success', schema=Schema( title='', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'url': Schema(type=TYPE_STRING, example= 'http://localhost:3030/api/feeds/ical/$TOKEN'), }, required=[ 'status', 'url', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response( description= 'Insufficient rights (administrator) (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=['role-professor', 'role-student']) def get(self, request): try: token = self._get_token(request) if token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) token, created = ICalToken.objects.get_or_create(user=token.user) return RF_Response({ 'status': 'success', 'url': f'{request.build_absolute_uri("/api/feeds/ical/")}{token}' }) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)
class ProfileViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Updates the user model.', operation_description='Should be accessible by every user.', responses={ 200: Response(description='Data updated', schema=Schema(title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), }, required=[ 'status', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, example='InvalidCredentials', enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response( description='Invalid old_password (code=`InvalidOldPassword`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, example='InvalidOldPassword', enum=error_codes), }, required=[ 'status', 'code', ])), 422: Response( description='Password too simple (code=`PasswordTooSimple`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, example='PasswordTooSimple', enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Profile', 'role-student', 'role-professor', ], request_body=Schema(title='ProfileUpdateRequest', type=TYPE_OBJECT, properties={ 'old_password': Schema(type=TYPE_STRING, example='12345'), 'new_password': Schema(type=TYPE_STRING, example='54321'), }, required=[ 'old_password', 'new_password', ])) def put(self, request, *args, **kwargs): try: token = self._get_token(request) correct_old_password = token.user.check_password( request.data['old_password']) if not correct_old_password: return RF_Response( { 'status': 'error', 'code': 'InvalidOldPassword' }, status=status.HTTP_403_FORBIDDEN) user = User.objects.get(id=token.user.id) try: validate_password(request.data['new_password']) user.set_password(request.data['new_password']) except ValidationError: return RF_Response( { 'status': 'error', 'code': 'PasswordTooSimple' }, status=status.HTTP_422_UNPROCESSABLE_ENTITY) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)
class ProfileLastOccupancyEdit(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary= 'Returns a list of all recent occupancies modifications that are relevant to the user.', operation_description= 'Modifications that are relevant are:\n- For a teacher: modifications of occupancies ' 'about a subject that they teach, or modifications of their own external occupancies.\n- ' 'For a student : modifications of occupancies about a subject that they take.\nOnly the ' 'last 25 modifications should be returned.', responses={ 200: Response( description='Recent modifications', schema=Schema( title='ProfileRecentModification', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'modifications': Schema( type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'modification_type': Schema(type=TYPE_STRING, enum=[ 'CREATION', 'EDIT', 'DELETION', ]), 'modification_timestamp': Schema(type=TYPE_INTEGER, example=1587987050), 'occupancy': Schema( type=TYPE_OBJECT, properties={ 'subject_name': Schema( type=TYPE_STRING, example= 'PPPE (nullable if external)'), 'class_name': Schema( type=TYPE_STRING, example= 'L3 Informatique (nullable if external' ), 'occupancy_type': Schema(type=TYPE_STRING, enum=occupancy_list), 'occupancy_start': Schema(type=TYPE_INTEGER, example=1587987050), 'occupancy_end': Schema(type=TYPE_INTEGER, example=1587987050), 'previous_occupancy_start': Schema( description= 'Only for the edition modification_type', type=TYPE_INTEGER, example=1587987050, ), 'previous_occupancy_end': Schema( description= 'Only for the edition modification_type', type=TYPE_INTEGER, example=1587987050), }, required=[ 'subject_name', 'class_name', 'occupancy_type', 'occupancy_start', 'occupancy_end', ]) }, required=[ 'modification_type', 'modification_timestamp', 'occupancy', ])) }, required=[ 'status', 'modifications', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), })), 403: Response( description= 'Insufficient rights (administrator) (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), })), }, tags=[ 'role-professor', 'role-student', ], ) def get(self, request): try: token = self._get_token(request) if token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) try: student = Student.objects.get(id=token.user.id) occ_modifications = OccupancyModification.objects.filter( occupancy__subject__studentsubject__student=student ).order_by('-modification_date')[:25] modifications = [] for occ in occ_modifications: occupancy = { 'subject_name': occ.occupancy.subject.name if occ.occupancy.occupancy_type != 'EXT' else None, 'class_name': occ.occupancy.subject._class.name if occ.occupancy.occupancy_type != 'EXT' else None, 'occupancy_type': occ.occupancy.occupancy_type, 'occupancy_start': occ.new_start_datetime.timestamp(), 'occupancy_end': (occ.new_start_datetime + occ.new_duration).timestamp(), } if occ.modification_type == 'EDITION': occupancy[ 'previous_occupancy_start'] = occ.previous_start_datetime.timestamp( ) occupancy['previous_occupancy_end'] = ( occ.previous_start_datetime + occ.previous_duration).timestamp() modifications.append({ 'modification_type': occ.modification_type, 'modification_timestamp': occ.modification_date.timestamp(), 'occupancy': occupancy }) return RF_Response({ 'status': 'success', 'modification': modifications }) except Student.DoesNotExist: pass except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)
class StudentDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets information for a student.', operation_description='Note : only users with the role `administrator` should be able to access this route.', responses={ 200: Response( description='Student information', schema=Schema( title='StudentResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'student': Schema( type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'username': Schema(type=TYPE_STRING, example='road_buddy'), 'total_hours': Schema(type=TYPE_INTEGER, example=166), 'subjects': Schema( type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'name': Schema(type=TYPE_STRING, example='Anglais'), 'group': Schema(type=TYPE_STRING, example='Groupe 1'), }, required=[ 'name', 'group', ] ) ) }, required=[ 'first_name', 'last_name', 'username', 'total_hours', 'subjects', ] ), }, required=['status', 'student', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Students', ] ) def get(self, request, student_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: student = Student.objects.get(id=student_id) def get_subjects() -> list: subject_list = [] student_subjects = StudentSubject.objects.filter(student=student) # TODO check this shit for s in student_subjects: subject_list.append( { 'name': s.subject.name, 'group': s.group_number, } ) return subject_list subjects = get_subjects() def count_hours() -> int: total = 0 return total student = { 'first_name': student.first_name, 'last_name': student.last_name, 'username': student.username, 'total_hours': count_hours(), 'subjects': subjects, } return RF_Response({'status': 'success', 'student': student}) except Student.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Updates information for a student.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'Only filled fields should be updated.', responses={ 200: Response( description='Student updated', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success') }, required=['status', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Password too simple (code=`PasswordTooSimple`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Students', ], request_body=Schema( title='StudentUpdateRequest', type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'class_id': Schema(type=TYPE_INTEGER, example=166), 'password': Schema(type=TYPE_STRING, example='new_password'), } ) ) def put(self, request, student_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: student = Student.objects.get(id=student_id) data = request.data data_keys = data.keys() if 'first_name' in data_keys: student.first_name = data['first_name'] if 'last_name' in data_keys: student.last_name = data['last_name'] if 'class_id' in data_keys: try: _class = Class.objects.get(id=data['class_id']) student._class = _class except Class.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) if 'password' in data_keys: try: validate_password(data['new_password']) student.set_password(data['new_password']) except ValidationError: return RF_Response({'status': 'error', 'code': 'PasswordTooSimple'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) student.save() return RF_Response({'status': 'success'}) except Student.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class GroupInvitationDetailViewSet(mixins.RetrieveModelMixin, mixins.DestroyModelMixin, AGModelGenericViewSet): serializer_class = ag_serializers.SubmissionGroupInvitationSerializer permission_classes = (invitation_detail_permissions, ) model_manager = ag_models.GroupInvitation.objects @swagger_auto_schema( responses={ '200': Response(schema=AGModelSchemaBuilder.get().get_schema( ag_models.GroupInvitation), description='You have accepted the invitation.'), '201': Response( schema=AGModelSchemaBuilder.get().get_schema(ag_models.Group), description='All invited users have accepted the invitation.') }) @transaction.atomic() @detail_route(methods=['POST']) def accept(self, request, *args, **kwargs): """ Accept this group invitation. If all invitees have accepted, create a group, delete the invitation, and return the group. """ invitation = self.get_object() invitation.invitee_accept(request.user) if not invitation.all_invitees_accepted: return response.Response(invitation.to_dict()) members = [invitation.invitation_creator] + list( invitation.invited_users.all()) utils.lock_users(members) # Keep this hook just after the users are locked test_ut.mocking_hook() serializer = ag_serializers.SubmissionGroupSerializer( data={ 'members': members, 'project': invitation.project }) serializer.is_valid() serializer.save() invitation.delete() return response.Response(serializer.data, status=status.HTTP_201_CREATED) @transaction.atomic() def destroy(self, request, *args, **kwargs): """ Revoke or reject this invitation. """ invitation = self.get_object() message = ("{} has rejected {}'s invitation to work together " "for project '{}'. The invitation has been deleted, " "and no groups have been created".format( request.user, invitation.invitation_creator.username, invitation.project.name)) for user in itertools.chain([invitation.invitation_creator], invitation.invited_users.all()): ag_models.Notification.objects.validate_and_create(message=message, recipient=user) invitation.delete() return response.Response(status=status.HTTP_204_NO_CONTENT)
class UserResponse(Serializer): id = serializers.IntegerField(label="일련번호", required=False) username = serializers.CharField(label="아이디", required=False) image = serializers.ImageField(label="이미지", required=False) nickname = serializers.CharField(label="닉네임", required=False) has_nickname = serializers.BooleanField(label="닉네임 작성여부", required=False) has_image = serializers.BooleanField(label="이미지 보유여부", required=False) class LoginResponse(Serializer): access_token = serializers.CharField(label="AccessToken", required=False) refresh_token = serializers.CharField(label="RefreshToken", required=False) user = UserResponse(read_only=True, required=False) login_response = Response("", LoginResponse) class IconResponse(Serializer): name = serializers.CharField(label="아이콘명") image = serializers.CharField(label="아이콘명", help_text="획득 시에는 활성화된 이미지가 내려갑니다.") acquired_date = serializers.CharField(label="획득일", required=False, allow_null=True) is_active = serializers.BooleanField(label="획득여부") class ProfileResponse(Serializer): nickname = serializers.CharField(label="닉네임", required=False) image = serializers.ImageField(label="프로필 이미지") complete_mission_count = serializers.IntegerField(label="달성한 미션수", required=False) post_count = serializers.IntegerField(label="게시물 수", required=False) experience = serializers.IntegerField(label="획득한 경험치", required=False)
class AuthViewSet(ObtainAuthToken, TokenHandlerMixin): @swagger_auto_schema( operation_summary= 'Logs in the user to the application, returning a new auth token and the user role.', operation_description='', responses={ 201: Response(description='Valid credentials', schema=Schema(title='SuccessfulLoginResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'token': Schema(type=TYPE_STRING, example='...'), 'user': Schema(type=TYPE_OBJECT, properties={ 'id': Schema(type=TYPE_INTEGER, example=166), 'first_name': Schema(type=TYPE_STRING), 'last_name': Schema(type=TYPE_STRING), 'kind': Schema(type=TYPE_STRING, enum=[ 'ADM', 'STU', 'TEA', ]) }, required=[ 'id', 'first_name', 'last_name', 'kind', ]) }, required=[ 'status', 'token', 'user', ])), 403: Response(description= 'Invalid credentials (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Auth', 'role-student', 'role-professor', ], request_body=Schema(title='LoginRequest', type=TYPE_OBJECT, properties={ 'username': Schema(type=TYPE_STRING, example='azure_diamond'), 'password': Schema(type=TYPE_STRING, example='hunter2'), }, required=[ 'username', 'password', ])) def post(self, request, *args, **kwargs): user = authenticate(request, username=request.data['username'], password=request.data['password']) if user is not None: def get_user_type(): if user.is_staff: return 'ADM' try: Teacher.objects.get(id=user.id) return 'TEA' except Teacher.DoesNotExist: pass try: Student.objects.get(id=user.id) return 'STU' except Student.DoesNotExist: pass token, created = Token.objects.get_or_create(user=user) response = { 'status': 'success', 'token': token.key, 'user': { 'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name, 'kind': get_user_type(), }, } login(request, user) return RF_Response(response, status=status.HTTP_201_CREATED) else: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_403_FORBIDDEN) @swagger_auto_schema( operation_summary='Destroys the given auth token.', operation_description='', responses={ 200: Response(description='Valid token', schema=Schema(title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success') }, required=['status'])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code'])) }, tags=[ 'Auth', 'role-student', 'role-professor', ], ) def delete(self, request, *args, **kwargs): try: token = self._get_token(request) if token.user: token.delete() logout(request) return RF_Response({'status': 'success'}) return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_403_FORBIDDEN) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_403_FORBIDDEN)
class OccupancyDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Updates information for a student.', operation_description= 'Note : only users with the role `administrator` should be able to access this route.\n' 'Only filled fields should be updated.', responses={ 200: Response(description='Student updated', schema=Schema(title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success') }, required=[ 'status', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response( description='Insufficient rights (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 404: Response( description= 'Invalid ID (code=`InvalidID`)\nInvalid classroom ID (code=`InvalidID`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 422: Response( description= 'The classroom is already occupied (code=`ClassroomAlreadyOccupied`)\nThe class (or group) ' 'is already occupied (code=`ClassOrGroupAlreadyOccupied`).\nEnd is before start ' '(code=`EndBeforeStart`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Occupancies', 'role-professor', ], request_body=Schema(title='OccupancyUpdateRequest', type=TYPE_OBJECT, properties={ 'classroom_id': Schema(type=TYPE_INTEGER, example=166), 'start': Schema(type=TYPE_INTEGER, example=166), 'end': Schema(type=TYPE_INTEGER, example=166), 'name': Schema(type=TYPE_STRING, example='new_password'), })) def put(self, request, student_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) try: occupancy = Occupancy.objects.get(id=student_id) data = request.data data_keys = data.keys() if 'classroom_id' in data_keys: try: classroom = Classroom.objects.get( id=data['classroom_id']) occupancy._class = classroom except Class.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidID' }, status=status.HTTP_404_NOT_FOUND) if 'start' in data_keys: occupancy.last_name = data['start'] if 'end' in data_keys: occupancy.duration = data['end'] - occupancy.start_datetime if 'name' in data_keys: occupancy.name = data['name'] occupancy.save() return RF_Response({'status': 'success'}) except Occupancy.DoesNotExist: return RF_Response({ 'status': 'error', 'code': 'InvalidID' }, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Deletes the given occupancies using their IDs.', operation_description= 'Note : only `administrators` and professors who are a teacher of the subject should be ' 'able to access this route.', responses={ 200: Response(description='Data deleted', schema=Schema(title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'success': Schema(type=TYPE_STRING, example='success'), }, required=[ 'success', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response( description='Insufficient rights (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 404: Response(description='Invalid ID(s) (code=`InvalidID`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Occupancies', 'role-professor', ], ) def delete(self, request, occupancy_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_401_UNAUTHORIZED) try: occupancy = Occupancy.objects.get(id=occupancy_id) occupancy.delete() return RF_Response({'status': 'success'}) except Occupancy.DoesNotExist: return RF_Response({ 'status': 'error', 'code': 'InvalidID' }, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)
class TeacherDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets information for a teacher.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'Warning: the `email` and `phone_number` can be null.', responses={ 200: Response( description='Teacher information', schema=Schema( title='TeacherResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'teacher': Schema( type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'username': Schema(type=TYPE_STRING, example='road_buddy'), 'email': Schema(type=TYPE_STRING, example='*****@*****.**'), 'phone_number': Schema(type=TYPE_STRING, example='06 61 66 16 61'), 'rank': Schema(type=TYPE_STRING, enum=ranks), 'total_services': Schema(type=TYPE_INTEGER, example=166), 'services': Schema( type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'class': Schema(type=TYPE_STRING, example='L3 INFORMATIQUE'), 'cm': Schema(type=TYPE_INTEGER, example=166), 'projet': Schema(type=TYPE_INTEGER, example=166), 'td': Schema(type=TYPE_INTEGER, example=166), 'tp': Schema(type=TYPE_INTEGER, example=166), 'administration': Schema(type=TYPE_INTEGER, example=166), 'external': Schema(type=TYPE_INTEGER, example=166), }, required=[ 'class', 'cm', 'projet', 'td', 'tp', 'administration', 'external', ] ) ) }, required=[ 'first_name', 'last_name', 'username', 'email', 'phone_number', 'rank', 'total_services', 'services', ] ), }, required=['status', 'teacher', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers', ] ) def get(self, request, teacher_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: teacher = Teacher.objects.get(id=teacher_id) def get_services() -> list: services = [] # TODO check this shit teacher_subjects = TeacherSubject.objects.filter(teacher=teacher) for ts in teacher_subjects: service_entry = {'class': teacher_subjects.subject._class.name} for s_type in service_list: try: occupancies = Occupancy.objects.get(teacher=teacher, occupancy_type=s_type, subject=ts.subject) except Occupancy.DoesNotExist: service_entry[occupancy_types[s_type]] = 0 continue total = 0 for occ in occupancies: total += occ.duration / 3600. service_entry[occupancy_types[s_type]] = total return services service_list = get_services() def count_service_value() -> int: coefficients = get_service_coefficients() total = 0 for entry in service_list: for k, v in coefficients: total += entry[occupancy_types[k]] * float(v) return total try: teacher = { 'first_name': teacher.first_name, 'last_name': teacher.last_name, 'username': teacher.username, 'email': teacher.email, 'phone_number': teacher.phone_number, 'rank': teacher.rank, 'total_services': count_service_value(), 'services': service_list, } except TeacherSubject.DoesNotExist: teacher = { 'first_name': teacher.first_name, 'last_name': teacher.last_name, 'username': teacher.username, 'email': teacher.email, 'phone_number': teacher.phone_number, 'rank': teacher.rank, 'total_services': 0, 'services': [], } return RF_Response({'status': 'success', 'teacher': teacher}) except Teacher.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Updates information for a teacher.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'Only filled fields should be updated. To remove the `phone_number` or `email` fields, ' 'pass `null`.', responses={ 200: Response( description='Teacher updated', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success') }, required=['status', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Invalid email (code=`InvalidEmail`)\nInvalid phone number (code=`InvalidPhoneNumber`)\n' 'Invalid rank (code=`InvalidRank`)\nPassword too simple (code=`PasswordTooSimple`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers', ], request_body=Schema( title='TeacherUpdateRequest', type=TYPE_OBJECT, properties={ 'first_name': Schema(type=TYPE_STRING, example='John'), 'last_name': Schema(type=TYPE_STRING, example='Doe'), 'email': Schema(type=TYPE_STRING, example='*****@*****.**'), 'phone_number': Schema(type=TYPE_STRING, example='06 61 66 16 61'), 'rank': Schema(type=TYPE_STRING, enum=ranks), 'password': Schema(type=TYPE_STRING, example='new_password'), } ) ) def put(self, request, teacher_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: teacher = Teacher.objects.get(id=teacher_id) data = request.data data_keys = data.keys() if 'first_name' in data_keys: teacher.first_name = data['first_name'] if 'last_name' in data_keys: teacher.last_name = data['last_name'] if 'email' in data_keys: try: validate_email(data['email']) teacher.email = data['email'] except ValidationError: return RF_Response({'status': 'error', 'code': 'InvalidEmail'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) if 'phone_number' in data_keys: try: phone_number_validator(data['phone_number']) teacher.phone_number = data['phone_number'] except ValidationError: return RF_Response({'status': 'error', 'code': 'InvalidPhoneNumber'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) if 'rank' in data_keys: if data['rank'] not in ranks: return RF_Response({'status': 'error', 'code': 'InvalidRank'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) teacher.rank = data['rank'] if 'password' in data_keys: try: validate_password(data['new_password']) teacher.set_password(data['new_password']) except ValidationError: return RF_Response({'status': 'error', 'code': 'PasswordTooSimple'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) teacher.save() return RF_Response({'status': 'success'}) except Teacher.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class ClassViewSet(GenericAPIView, TokenHandlerMixin): serializer_class = ClassSerializer queryset = Class.objects.all() pagination_class = ClassResultSetPagination def get_queryset(self): queryset = super().get_queryset() query = self.request.query_params.get('query', None) if query: if len(query) >= 3: queryset = queryset.filter( Q(name__unaccent__icontains=query) ) return queryset.order_by('name') @swagger_auto_schema( operation_summary='Returns a paginated list of all classes.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n10' ' classes should be returned per page. At least three characters should be provided for ' 'the search, or the results won\'t be filtered.', responses={ 200: Response( description='A list of all classes.', schema=Schema( title='ClassesList', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'total': Schema(type=TYPE_INTEGER, description='Total number of classes', example=166), 'classes': Schema( type=TYPE_ARRAY, items=Schema( title='ClassWithId', type=TYPE_OBJECT, properties={ 'id': Schema(type=TYPE_INTEGER, example=166), 'name': Schema(type=TYPE_STRING, example='L3 Informatique'), 'level': Schema(type=TYPE_STRING, enum=levels), }, required=['id', 'name', 'level', ] ), ), }, required=['status', 'total', 'classes', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Classes'], manual_parameters=[ Parameter(name='query', in_=IN_QUERY, type=TYPE_STRING, required=False), ], ) def get(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) result = self.get_paginated_response(serializer.data) response = result.data else: serializer = self.get_serializer(queryset, many=True) response = serializer.data data = { 'status': 'success', 'total': response['count'], 'classes': response['results'], } return RF_Response(data) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except NotFound: data = { 'status': 'success', 'total': len(self.get_queryset()), 'teachers': [], } return RF_Response(data) @swagger_auto_schema( operation_summary='Creates a new class.', operation_description='Note : only users with the role `administrator` should be able to access this route.', responses={ 201: Response( description='Class created', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), }, required=['status', ])), 401: Response( description='Unauthorized access', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Invalid level (code=`InvalidLevel`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Classes'], request_body=Schema( title='ClassCreationRequest', type=TYPE_OBJECT, properties={ 'name': Schema(type=TYPE_STRING, example='L3 Informatique'), 'level': Schema(type=TYPE_STRING, enum=levels), }, required=['name', 'level', ] ) ) def post(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) serializer = ClassCreationSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return RF_Response(serializer.data, status=status.HTTP_201_CREATED) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Deletes the given classes using their IDs.', operation_description='Note : only users with the role `administrator` should be able to access this route.\n' 'This request should be denied if the class is used in any subject, or if any student is' ' in this class.', responses={ 200: Response( description='Data deleted', schema=Schema( title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), }, required=['status', ])), 401: Response( description='Unauthorized access', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 422: Response( description='Class is still used by a subject (code=`ClassUsed`)\nA student is still in this class ' '(code=`StudentInClass`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema( type=TYPE_STRING, example='error'), 'code': Schema( type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Classes'], request_body=Schema( title='IDRequest', type=TYPE_ARRAY, items=Schema( type=TYPE_INTEGER, example=166 ) ), ) def delete(self, request, *args, **kwargs): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_401_UNAUTHORIZED) def delete_class(class_id: int): _class = Class.objects.get(id=class_id) _class.delete() for post_id in request.data: try: delete_class(post_id) except Class.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) return RF_Response({'status': 'success'}) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class TeacherSubjectDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets the list of all subjects that a teacher participates in.', operation_description='Note : only teachers whose id match the one in the URL should be able to access this ' 'route.', responses={ 200: Response( description='Teacher information', schema=Schema( title='TeacherSubjects', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'subjects': Schema( type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'id': Schema(type=TYPE_INTEGER, example=166), 'name': Schema(type=TYPE_STRING, example='PPPE'), 'class_name': Schema(type=TYPE_STRING, example='L3 INFORMATIQUE'), 'teachers': teacher_list_schema, 'groups': Schema( type=TYPE_ARRAY, items=Schema( type=TYPE_OBJECT, properties={ 'number': Schema(type=TYPE_INTEGER, example=166), 'name': Schema(type=TYPE_STRING, example='Groupe 1'), 'count': Schema(type=TYPE_INTEGER, example=166), }, required=['number', 'name', 'count', ] ) ), }, required=['id', 'name', 'class_name', 'teachers', 'groups', ] ), ), }, required=['status', 'subjects', ] ) ), 401: Response( description='Invalid token (code=`InvalidCredentials`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 403: Response( description='Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), 404: Response( description='Invalid ID(s) (code=`InvalidID`)', schema=Schema( title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=['status', 'code', ] ) ), }, tags=['Teachers', 'role-professor', ] ) def get(self, request, teacher_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response({'status': 'error', 'code': 'InsufficientAuthorization'}, status=status.HTTP_403_FORBIDDEN) try: teacher = Teacher.objects.get(id=teacher_id) def get_subjects() -> list: subject_list = [] student_subjects = TeacherSubject.objects.filter(teacher=teacher) # TODO check this shit for ss in student_subjects: def get_subject_teachers() -> list: teachers = [] teacher_subjects = TeacherSubject.objects.filter(subject=ss.subject) for t in teacher_subjects: teachers.append( { 'first_name': t.teacher.first_name, 'last_name': t.teacher.last_name, 'in_charge': t.in_charge, 'email': t.teacher.email, 'phone_number': t.teacher.phone_number, } ) return teachers def get_subject_groups() -> list: groups = [] for i in range(1, ss.subject.group_count + 1): groups.append( { 'number': i, 'name': f'Groupe {i}', 'count': group_size(i), } ) return groups subject_list.append( { 'id': ss.subject.id, 'name': ss.subject.name, 'class_name': ss.subject._class.name, 'teachers': get_subject_teachers(), 'groups': get_subject_groups(), } ) return subject_list response = { 'status': 'success', 'subjects': get_subjects(), } return RF_Response(response) except Teacher.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidID'}, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response({'status': 'error', 'code': 'InvalidCredentials'}, status=status.HTTP_401_UNAUTHORIZED)
class ClassroomDetailViewSet(APIView, TokenHandlerMixin): @swagger_auto_schema( operation_summary='Gets information for a classroom.', operation_description= 'Note : only users with the role `administrator` should be able to access this route.', responses={ 200: Response(description='Teacher information', schema=Schema(title='TeacherResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), 'classroom': Schema(title='Classroom', type=TYPE_OBJECT, properties={ 'id': Schema(type=TYPE_INTEGER, example=166), 'name': Schema(type=TYPE_STRING, example='B.001'), 'capacity': Schema(type=TYPE_STRING, example=166), }, required=[ 'id', 'name', 'capacity', ]), }, required=[ 'status', 'classroom', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response(description= 'Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 404: Response(description='Invalid ID(s) (code=`InvalidID`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Classrooms', ]) def get(self, request, classroom_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) try: classroom = Classroom.objects.get(id=classroom_id) classroom = { 'id': classroom.id, 'name': classroom.name, 'capacity': classroom.capacity, } return RF_Response({ 'status': 'success', 'classroom': classroom }) except Classroom.DoesNotExist: return RF_Response({ 'status': 'error', 'code': 'InvalidID' }, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) @swagger_auto_schema( operation_summary='Updates information for a classroom.', operation_description= 'Note : only users with the role `administrator` should be able to access this route.\n' 'The omission of the `capacity` field is not an error : it should not be able to be ' 'modified.', responses={ 200: Response(description='Data updated', schema=Schema(title='SimpleSuccessResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='success'), }, required=[ 'status', ])), 401: Response(description='Invalid token (code=`InvalidCredentials`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 403: Response(description= 'Insufficient rights (code=`InsufficientAuthorization`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), 404: Response(description='Invalid ID(s) (code=`InvalidID`)', schema=Schema(title='ErrorResponse', type=TYPE_OBJECT, properties={ 'status': Schema(type=TYPE_STRING, example='error'), 'code': Schema(type=TYPE_STRING, enum=error_codes), }, required=[ 'status', 'code', ])), }, tags=[ 'Classrooms', ], request_body=Schema(title='ClassroomUpdateRequest', type=TYPE_OBJECT, properties={ 'name': Schema(type=TYPE_STRING, example='B.001'), }, required=[ 'name', ])) def put(self, request, classroom_id): try: token = self._get_token(request) if not token.user.is_staff: return RF_Response( { 'status': 'error', 'code': 'InsufficientAuthorization' }, status=status.HTTP_403_FORBIDDEN) try: classroom = Classroom.objects.get(id=classroom_id) classroom.name = request.data['name'] classroom.save() return RF_Response({ 'status': 'success', }) except Classroom.DoesNotExist: return RF_Response({ 'status': 'error', 'code': 'InvalidID' }, status=status.HTTP_404_NOT_FOUND) except Token.DoesNotExist: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED) except AttributeError: return RF_Response( { 'status': 'error', 'code': 'InvalidCredentials' }, status=status.HTTP_401_UNAUTHORIZED)