From 3259ebb3615768716e4f8dde7c84cb5ca08ae1f0 Mon Sep 17 00:00:00 2001 From: ingo <ingo.leindecker@fro.at> Date: Mon, 18 Dec 2017 19:31:33 +0100 Subject: [PATCH] More endpoints and improvements. Problem to solve: there's a mix between API usecases for Playlist-UI and Website. See #22 --- program/models.py | 15 +- program/serializers.py | 129 ++++++++++++++++- program/views.py | 312 +++++++++++++++++++---------------------- pv/settings.py | 7 - pv/urls.py | 12 +- 5 files changed, 285 insertions(+), 190 deletions(-) diff --git a/program/models.py b/program/models.py index 570169a5..e856f8cd 100644 --- a/program/models.py +++ b/program/models.py @@ -255,7 +255,7 @@ class Host(models.Model): ppoi = PPOIField('Image PPOI') height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False) width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False) - image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='user_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.")) + image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='host_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.")) class Meta: ordering = ('name',) @@ -321,6 +321,19 @@ class Show(models.Model): def active_schedules(self): return self.schedules.filter(until__gt=date.today()) + def is_editable(self, show_id): + """ + Whether the current user can edit the given show + @return boolean + """ + if self.request.user.is_superuser: + show_ids = Show.objects.all().values_list('id', flat=True) + else: + show_ids = self.request.user.shows.all().values_list('id', flat=True) + + return int(show_id) in show_ids + + class RRule(models.Model): diff --git a/program/serializers.py b/program/serializers.py index 47594149..3b5ce0cb 100644 --- a/program/serializers.py +++ b/program/serializers.py @@ -13,8 +13,24 @@ class UserSerializer(serializers.ModelSerializer): class Meta: model = User - exclude = ('password',) - #fields = '__all__' + fields = '__all__' + + + def create(self, validated_data): + """ + Create and return a new User instance, given the validated data. + """ + + profile_data = validated_data.pop('profile') + user = super(UserSerializer, self).create(validated_data) + user.date_joined = datetime.today() + user.set_password(validated_data['password']) + user.save() + + profile = Profile(user=user, cba_username=profile_data.get('cba_username'), cba_user_token=profile_data.get('cba_user_token')) + profile.save() + + return user def update(self, instance, validated_data): @@ -27,7 +43,11 @@ class UserSerializer(serializers.ModelSerializer): instance.email = validated_data.get('email', instance.email) # TODO: How to hook into this from ProfileSerializer without having to call it here? - profile = Profile.objects.get(user=instance.id) + try: + profile = Profile.objects.get(user=instance.id) + except ObjectDoesNotExist: + profile = Profile.objects.create(user=instance, **validated_data['profile']) + profile.cba_username = validated_data['profile'].get('cba_username') profile.cba_user_token = validated_data['profile'].get('cba_user_token') profile.save() @@ -36,21 +56,39 @@ class UserSerializer(serializers.ModelSerializer): return instance + class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing Category instance, given the validated data. + """ + instance.category = validated_data.get('category', instance.category) + instance.abbrev = validated_data.get('abbrev', instance.abbrev) + instance.slug = validated_data.get('slug', instance.slug) + instance.color = validated_data.get('color', instance.color) + instance.description = validated_data.get('description', instance.description) + + instance.save() + return instance + + class HostSerializer(serializers.ModelSerializer): class Meta: model = Host fields = '__all__' + def update(self, instance, validated_data): """ Update and return an existing Host instance, given the validated data. """ + + # TODO: Still put this into a sub app? instance.name = validated_data.get('name', instance.name) instance.is_always_visible = validated_data.get('is_always_visible', instance.is_always_visible) instance.email = validated_data.get('email', instance.email) @@ -75,30 +113,90 @@ class LanguageSerializer(serializers.ModelSerializer): fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing Language instance, given the validated data. + """ + instance.name = validated_data.get('name', instance.name) + + instance.save() + return instance + + class TopicSerializer(serializers.ModelSerializer): class Meta: model = Topic fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing Topic instance, given the validated data. + """ + instance.topic = validated_data.get('topic', instance.topic) + instance.abbrev = validated_data.get('abbrev', instance.abbrev) + instance.slug = validated_data.get('slug', instance.slug) + + instance.save() + return instance + + class MusicFocusSerializer(serializers.ModelSerializer): class Meta: model = MusicFocus fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing MusicFocus instance, given the validated data. + """ + instance.focus = validated_data.get('focus', instance.focus) + instance.abbrev = validated_data.get('abbrev', instance.abbrev) + instance.slug = validated_data.get('slug', instance.slug) + + instance.save() + return instance + + class TypeSerializer(serializers.ModelSerializer): class Meta: model = Type fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing Type instance, given the validated data. + """ + instance.type = validated_data.get('type', instance.type) + instance.slug = validated_data.get('slug', instance.slug) + instance.color = validated_data.get('color', instance.color) + instance.text_color = validated_data.get('text_color', instance.text_color) + instance.enabled = validated_data.get('enabled', instance.enabled) + + instance.save() + return instance + + class RTRCategorySerializer(serializers.ModelSerializer): class Meta: model = RTRCategory fields = '__all__' + def update(self, instance, validated_data): + """ + Update and return an existing RTRCategory instance, given the validated data. + """ + instance.rtrcategory = validated_data.get('rtrcategory', instance.rtrcategory) + instance.abbrev = validated_data.get('abbrev', instance.abbrev) + instance.slug = validated_data.get('slug', instance.slug) + + instance.save() + return instance + + ''' class OwnersSerializer(serializers.ModelSerializer): class Meta: @@ -106,6 +204,7 @@ class OwnersSerializer(serializers.ModelSerializer): fields = '__all__' ''' + class ShowSerializer(serializers.HyperlinkedModelSerializer): category = CategorySerializer(many=True) hosts = HostSerializer(many=True) @@ -143,16 +242,36 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer): instance.website = validated_data.get('website', instance.website) instance.cba_series_id = validated_data.get('cba_series_id', instance.cba_series_id) instance.fallback_pool = validated_data.get('fallback_pool', instance.fallback_pool) + instance.save() return instance +# TODO: collision detection +class ScheduleSerializer(serializers.ModelSerializer): + class Meta: + model = Schedule + fields = '__all__' + + def create(self, validated_data): + """ + Create and return a new Schedule instance, given the validated data. + """ + return Schedule.objects.create(**validated_data) + + + def update(self, instance, validated_data): + """ + Update and return an existing Schedule instance, given the validated data. + """ + return instance + + class TimeSlotSerializer(serializers.ModelSerializer): class Meta: model = TimeSlot fields = '__all__' - def create(self, validated_data): """ Create and return a new TimeSlot instance, given the validated data. @@ -177,7 +296,6 @@ class NoteSerializer(serializers.ModelSerializer): model = Note fields = '__all__' - def create(self, validated_data): """ Create and return a new Note instance, given the validated data. @@ -200,5 +318,6 @@ class NoteSerializer(serializers.ModelSerializer): instance.image = validated_data.get('image', instance.image) instance.status = validated_data.get('status', instance.status) instance.cba_id = validated_data.get('cba_id', instance.cba_id) + instance.save() return instance \ No newline at end of file diff --git a/program/views.py b/program/views.py index 85f468dc..001ee661 100644 --- a/program/views.py +++ b/program/views.py @@ -14,13 +14,13 @@ from django.views.generic.list import ListView from rest_framework import permissions, serializers, status, viewsets from rest_framework.views import APIView from rest_framework.response import Response - -from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope +from rest_framework.decorators import detail_route from program.models import Type, MusicFocus, Language, Note, Show, Category, RTRCategory, Topic, TimeSlot, Host, Schedule -from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, CategorySerializer, RTRCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, UserSerializer +from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, ScheduleSerializer, CategorySerializer, RTRCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, UserSerializer from program.utils import tofirstdayinisoweek, get_cached_shows + class CalendarView(TemplateView): template_name = 'calendar.html' @@ -320,44 +320,6 @@ def json_timeslots_specials(request): content_type="application/json; charset=utf-8") -def json_get_timeslots_by_show(request): - ''' - Returns a JSON object of timeslots of a given show from 4 weeks ago until 12 weeks in the future - Called by /api/v1/timeslots/?show_id=1 to populate a timeslot-select for being assigned to a note - ''' - - if not request.user.is_authenticated(): - return JsonResponse(_('Permission denied.')) - - if request.method == 'GET' and request.GET.get('show_id') != None: - - four_weeks_ago = datetime.now() - timedelta(weeks=4) - in_twelve_weeks = datetime.now() + timedelta(weeks=12) - - timeslots = [] - saved_timeslot_id = 0 if request.GET.get('timeslot_id') == None else int(request.GET.get('timeslot_id')) - - # If the saved timeslot is part of the currently selected show, - # include it as the first select-option in order not to lose it if it's past - if saved_timeslot_id > 0: - try: - saved_timeslot = TimeSlot.objects.get(pk=int(request.GET.get('timeslot_id')),show=int(request.GET.get('show_id'))) - timeslots.append( { 'timeslot': str(saved_timeslot), 'timeslot_id': saved_timeslot.id, 'start': saved_timeslot.start, 'end': saved_timeslot.end } ) - except ObjectDoesNotExist: - pass - - for timeslot in TimeSlot.objects.filter(show=int(request.GET.get('show_id')), - start__gt=four_weeks_ago, - start__lt=in_twelve_weeks).exclude(pk=saved_timeslot_id): - - timeslots.append( { 'timeslot': str(timeslot), 'timeslot_id' : timeslot.id, 'start': timeslot.start, 'end': timeslot.end } ) - - return JsonResponse( timeslots, safe=False ) - - else: - return JsonResponse( _('No show_id given.'), safe=False ) - - #################################################################### @@ -373,39 +335,36 @@ class APIUserViewSet(viewsets.ModelViewSet): Superusers may access and update all users """ - permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] #, TokenHasReadWriteScope] + permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] serializer_class = UserSerializer - queryset = User.objects.all() + queryset = User.objects.none() required_scopes = ['users'] - def list(self, request): - # Commons users only see themselves - if request.user.is_superuser: - users = User.objects.all() + + def get_queryset(self): + """Constrain access to oneself except for superusers""" + if self.request.user.is_superuser: + return User.objects.all() else: - users = User.objects.filter(pk=request.user.id) + return User.objects.filter(pk=self.request.user.id) + + def list(self, request): + users = self.get_queryset() serializer = UserSerializer(users, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): """Returns a single user""" - if pk != None: - pk = int(pk) - try: - user = User.objects.get(pk=pk) - except ObjectDoesNotExist: - return Response(status=status.HTTP_404_NOT_FOUND) - - # Common users may only see themselves - if not request.user.is_superuser and user.id != request.user.id: - return Response(status=status.HTTP_401_UNAUTHORIZED) + user = get_object_or_404(User, pk=pk) - serializer = UserSerializer(user) - return Response(serializer.data) + # Common users may only see themselves + if not request.user.is_superuser and user.id != request.user.id: + return Response(status=status.HTTP_401_UNAUTHORIZED) - return Response(status=status.HTTP_400_BAD_REQUEST) + serializer = UserSerializer(user) + return Response(serializer.data) def partial_update(self, request, pk=None): @@ -423,29 +382,76 @@ class APIUserViewSet(viewsets.ModelViewSet): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + class APIShowViewSet(viewsets.ModelViewSet): """ - /api/v1/shows/ Returns shows a user owns - /api/v1/shows/1 Used for retrieving a single show or update (if owned) + /api/v1/shows/ Returns shows a user owns + /api/v1/shows/?active=true Returns all active shows (no matter if owned by user) + /api/v1/shows/1 Used for retrieving a single show or update (if owned) + /api/v1/shows/1/schedules Returns all schedules for the given show + /api/v1/shows/1/timeslots Returns all timeslots for the given show + /api/v1/shows/1/timeslots?start=2017-01-01&end=2017-12-31 Returns all timeslots for the given show Superusers may access and update all shows """ - queryset = Show.objects.all() + queryset = Show.objects.none() serializer_class = ShowSerializer - permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] #, TokenHasReadWriteScope] + permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] required_scopes = ['shows'] - def list(self, request): - """Lists all shows""" + def get_queryset(self): + """Constrain access to owners except for superusers""" + + if self.request.GET.get('active') == 'true': + '''Filter for retrieving currently running shows''' + + # Get currently running schedules to filter by + # For single dates we test if there'll be one in the future (and ignore the until date) + # TODO: Really consider dstart? (=currently active, not just upcoming ones) + schedules = Schedule.objects.filter( Q(rrule_id__gt=1,dstart__lte=date.today(),until__gte=date.today()) | + Q(rrule_id=1,dstart__gte=date.today()) ).distinct().values_list('show_id', flat=True) + + return Show.objects.filter(id__in=schedules) - # Commons users only see shows they own - if request.user.is_superuser: - shows = Show.objects.all() + if self.request.user.is_superuser: + return Show.objects.all() else: - shows = request.user.shows.all() + return self.request.user.shows.all() + + @detail_route(methods=['get'], url_path='schedules') + def schedules(self, request, pk=None): + """Return all schedules of the show""" + show = get_object_or_404(Show, pk=pk) + schedules = Schedule.objects.filter(show=show) + serializer = ScheduleSerializer(schedules, many=True) + return Response(serializer.data) + + + @detail_route(methods=['get'], url_path='timeslots') + def timeslots(self, request, pk=None): + """Return timeslots of the show for the next 60 days or the given timerange""" + show = get_object_or_404(Show, pk=pk) + + # Return next 60 days by default + start = datetime.combine(date.today(), time(0, 0)) + end = start + timedelta(days=60) + + if self.request.GET.get('start') and self.request.GET.get('end'): + start = datetime.combine( datetime.strptime(self.request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0)) + end = datetime.combine( datetime.strptime(self.request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59)) + + timeslots = TimeSlot.objects.filter(show=show, start__gte=start, end__lte=end).order_by('start') + serializer = TimeSlotSerializer(timeslots, many=True) + return Response(serializer.data) + + + def list(self, request): + """Lists shows""" + shows = self.get_queryset() serializer = ShowSerializer(shows, many=True) return Response(serializer.data) @@ -457,30 +463,16 @@ class APIShowViewSet(viewsets.ModelViewSet): def retrieve(self, request, pk=None): """Returns a single show""" - - if pk != None and int(pk): - pk = int(pk) - - # Common users may only retrieve shows they own - if not request.user.is_superuser and pk not in list(request.user.shows.all().values_list('id', flat=True)): - return Response(status=status.HTTP_401_UNAUTHORIZED) - - try: - show = Show.objects.get(pk=pk) - except ObjectDoesNotExist: - return Response(status=status.HTTP_404_NOT_FOUND) - - serializer = ShowSerializer(show) - return Response(serializer.data) - - return Response(status=status.HTTP_400_BAD_REQUEST) + show = get_object_or_404(Show, pk=pk) + serializer = ShowSerializer(show) + return Response(serializer.data) def partial_update(self, request, pk=None): serializer = ShowSerializer(data=request.data) # For common user and not owner of show: Permission denied - if not request.user.is_superuser and int(pk) not in list(request.user.shows.all().values_list('id', flat=True)): + if not Show.is_editable(self, pk): return Response(serializer.initial_data, status=status.HTTP_401_UNAUTHORIZED) if serializer.is_valid(): @@ -490,52 +482,51 @@ class APIShowViewSet(viewsets.ModelViewSet): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - def destroy(self, request, pk=None): - '''Deleting is not allowed at the moment''' - return Response(status=status.HTTP_401_UNAUTHORIZED) - - class APITimeSlotViewSet(viewsets.ModelViewSet): """ - /api/v1/timeslots Returns nothing + /api/v1/timeslots Returns timeslots of the next 60 days + /api/v1/timeslots/?start=2017-01-01&end=2017-02-01 Returns timeslots within the given timerange /api/v1/timeslots/?show_id=1 Returns upcoming timeslots of a show 60 days in the future /api/v1/timeslots/?show_id=1&start=2017-01-01&end=2017-02-01 Returns timeslots of a show within the given timerange - - TODO: Test for permissions to show """ - permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] #, TokenHasReadWriteScope] + permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] serializer_class = TimeSlotSerializer - queryset = TimeSlot.objects.all() + queryset = TimeSlot.objects.none() required_scopes = ['timeslots'] - def list(self, request): - """Lists timeslots of a show""" + def get_queryset(self): + # Return next 60 days by default + start = datetime.combine(date.today(), time(0, 0)) + end = start + timedelta(days=60) - if request.GET.get('show_id') != None: - show_id = int(request.GET.get('show_id')) + if self.request.GET.get('start') and self.request.GET.get('end'): + start = datetime.combine( datetime.strptime(self.request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0)) + end = datetime.combine( datetime.strptime(self.request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59)) - if not request.user.is_superuser and show_id not in list(request.user.shows.all().values_list('id', flat=True)): - return Response(status=status.HTTP_401_UNAUTHORIZED) + # If show is given: Return corresponding timeslots + if self.request.GET.get('show_id') != None: + show_id = int(self.request.GET.get('show_id')) - # Return next 60 days by default - start = datetime.combine(date.today(), time(0, 0)) - end = start + timedelta(days=60) + if not Show.is_editable(self, show_id): + return Response(status=status.HTTP_401_UNAUTHORIZED) - if request.GET.get('start') and request.GET.get('end'): - start = datetime.combine( datetime.strptime(request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0)) - end = datetime.combine( datetime.strptime(request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59)) + return TimeSlot.objects.filter(show=show_id, start__gte=start, end__lte=end).order_by('start') - timeslots = TimeSlot.objects.filter(show=show_id, start__gte=start, end__lte=end).order_by('start') - serializer = TimeSlotSerializer(timeslots, many=True) + # Otherwise return all show timeslots + return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by('start') - return Response(serializer.data) - return Response(status=status.HTTP_400_BAD_REQUEST) + def list(self, request): + """Lists timeslots of a show""" + timeslots = self.get_queryset() + serializer = TimeSlotSerializer(timeslots, many=True) + return Response(serializer.data) def create(self, request): + """Timeslots may only be created by adding/updating schedules""" return Response(status=HTTP_401_UNAUTHORIZED) @@ -550,40 +541,41 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - def destroy(self, request, pk=None): - """Deleting is not allowed at the moment""" - return Response(status=status.HTTP_401_UNAUTHORIZED) - - class APINoteViewSet(viewsets.ModelViewSet): """ - /api/v1/notes/ Returns nothing + /api/v1/notes/ Returns all notes the user owns /ap1/v1/notes/1 Returns a single note (if owned) /api/v1/notes/?ids=1,2,3,4,5 Returns given notes (if owned) Superusers may access and update all notes """ - queryset = Note.objects.all() + queryset = Note.objects.none() serializer_class = NoteSerializer - permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] #, TokenHasReadWriteScope] + permission_classes = [permissions.IsAuthenticated, permissions.DjangoModelPermissions] required_scopes = ['notes'] - def list(self, request): - """Lists notes""" + def get_queryset(self): - if request.GET.get('ids') != None: - note_ids = request.GET.get('ids').split(',') - if request.user.is_superuser: + # TODO: Should users be able to edit other's notes if they're part of a show they own? + if self.request.GET.get('ids') != None: + note_ids = self.request.GET.get('ids').split(',') + if self.request.user.is_superuser: notes = Note.objects.filter(id__in=note_ids) else: # Common users only retrieve notes they own - notes = Note.objects.filter(id__in=note_ids,user=request.user.id) + notes = Note.objects.filter(id__in=note_ids,user=self.request.user.id) else: - notes = Note.objects.none() + notes = Note.objects.filter(user=self.request.user.id) + + return notes + + def list(self, request): + """Lists notes""" + notes = self.get_queryset() serializer = NoteSerializer(notes, many=True) return Response(serializer.data) @@ -591,13 +583,15 @@ class APINoteViewSet(viewsets.ModelViewSet): def create(self, request): """ Creates a note - TODO: Test! """ # Only create a note if show_id and timeslot_id is given - if not int(validated_data.get('show_id')) and not int(validated_data.get('timeslot_id')): + if request.POST.get('show') == None or request.POST.get('timeslot') == None: return Response(status=status.HTTP_400_BAD_REQUEST) + if not Show.is_editable(self, request.POST.get('show')): + return Response(status=status.HTTP_401_UNAUTHORIZED) + serializer = NoteSerializer(data=request.data) if serializer.is_valid(): serializer.save() @@ -609,56 +603,38 @@ class APINoteViewSet(viewsets.ModelViewSet): def retrieve(self, request, pk=None): """Returns a single note""" - if pk != None: - try: - note = Note.objects.get(pk=pk) - except ObjectDoesNotExist: - return Response(status=status.HTTP_404_NOT_FOUND) + note = get_object_or_404(Note, pk=pk) - if not request.user.is_superuser and note.user_id != request.user.id: - return Response(status=status.HTTP_401_UNAUTHORIZED) + if not request.user.is_superuser and int(pk) not in self.get_queryset().values_list('id', flat=True): + return Response(status=status.HTTP_401_UNAUTHORIZED) - serializer = NoteSerializer(note) - return Response(serializer.data) - - return Response(status=status.HTTP_400_BAD_REQUEST) + serializer = NoteSerializer(note) + return Response(serializer.data) def partial_update(self, request, pk=None): - if pk != None: - pk = int(pk) - try: - note = Note.objects.get(pk=pk) - except ObjectDoesNotExist: - return Response(status=status.HTTP_404_NOT_FOUND) - - if not request.user.is_superuser and note.user_id != request.user.id: - return Response(status=status.HTTP_401_UNAUTHORIZED) + note = get_object_or_404(Note, pk=pk) - serializer = NoteSerializer(data=request.data) + if not request.user.is_superuser and note.user_id != request.user.id: + return Response(status=status.HTTP_401_UNAUTHORIZED) - if serializer.is_valid(): - serializer.save(); - return Response(serializer.data) + serializer = NoteSerializer(data=request.data) + + if serializer.is_valid(): + serializer.save(); + return Response(serializer.data) return Response(status=status.HTTP_400_BAD_REQUEST) def destroy(self, request, pk=None): - if pk != None: - pk = int(pk) - try: - note = Note.objects.get(pk=pk) - except ObjectDoesNotExist: - return Response(status.HTTP_404_NOT_FOUND) - - if not request.user.is_superuser and note.user_id != request.user.id: - return Response(status=status.HTTP_401_UNAUTHORIZED) + note = get_object_or_404(Note, pk=pk) - Note.objects.delete(pk=pk) - return Response(status=status.HTTP_204_NO_CONTENT) + if not request.user.is_superuser and note.user_id != request.user.id: + return Response(status=status.HTTP_401_UNAUTHORIZED) - return Response(status=status.HTTP_400_BAD_REQUEST) + Note.objects.delete(pk=pk) + return Response(status=status.HTTP_204_NO_CONTENT) class APICategoryViewSet(viewsets.ModelViewSet): diff --git a/pv/settings.py b/pv/settings.py index 06595ae1..74d3a2c8 100644 --- a/pv/settings.py +++ b/pv/settings.py @@ -77,11 +77,6 @@ MIDDLEWARE_CLASSES = ( ROOT_URLCONF = 'pv.urls' -OAUTH2_PROVIDER = { - # this is the list of available scopes - 'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'shows': 'Access to shows', 'notes': 'Access to notes', 'timeslots': 'Access to timeslots'} -} - REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. @@ -90,7 +85,6 @@ REST_FRAMEWORK = { #'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ], 'DEFAULT AUTHENTICATION_CLASSES': [ - 'oauth2_provider.ext.rest_framework.OAuth2Authentication', ] } @@ -108,7 +102,6 @@ INSTALLED_APPS = ( 'tinymce', 'versatileimagefield', 'rest_framework', - 'oauth2_provider', 'frapp', ) diff --git a/pv/urls.py b/pv/urls.py index 22e5e94c..ea38cf19 100644 --- a/pv/urls.py +++ b/pv/urls.py @@ -5,9 +5,7 @@ from django.views.static import serve from rest_framework import routers from rest_framework.authtoken import views -from program.views import APIUserViewSet, APIHostViewSet, APIShowViewSet, APITimeSlotViewSet, APINoteViewSet, APICategoryViewSet, APITypeViewSet, APITopicViewSet, APIMusicFocusViewSet, APIRTRCategoryViewSet, APILanguageViewSet, json_day_schedule, json_week_schedule, json_timeslots_specials, json_get_timeslots_by_show - -from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope +from program.views import APIUserViewSet, APIHostViewSet, APIShowViewSet, APITimeSlotViewSet, APINoteViewSet, APICategoryViewSet, APITypeViewSet, APITopicViewSet, APIMusicFocusViewSet, APIRTRCategoryViewSet, APILanguageViewSet, json_day_schedule, json_week_schedule, json_timeslots_specials admin.autodiscover() @@ -26,18 +24,14 @@ router.register(r'rtrcategories', APIRTRCategoryViewSet) router.register(r'languages', APILanguageViewSet) urlpatterns = [ - url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), - url(r'^api-token-auth/', views.obtain_auth_token), url(r'^api/v1/', include(router.urls) ), - url(r'^api/v1/program$', json_week_schedule), - url(r'^api/v1/timeslots-by-show$', json_get_timeslots_by_show, name='json_get_timeslots_by_show'), - url(r'^api/v1/week_schedule$', json_week_schedule), + url(r'^api/v1/program/week', json_week_schedule), + url(r'^api/v1/program/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', json_day_schedule), url(r'^admin/', admin.site.urls), url(r'^program/', include('program.urls')), url(r'^nop', include('nop.urls')), url(r'^', include('frapp.urls')), #url(r'^tinymce/', include('tinymce.urls')), - url(r'^export/day_schedule/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', json_day_schedule), url(r'^export/timeslots_specials.json$', json_timeslots_specials), ] -- GitLab