Axios删除将导致未经授权的401

时间:2019-07-12 09:28:39

标签: javascript python django reactjs

当尝试通过Axios删除事件时,出现401错误。

我已使应用程序内的所有用户具有删除事件权限的超级用户和管理员。但是,在后端纠正了这一问题并更新了我的登台服务器之后,我仍然遇到401错误。

Eventdetails.js

import React from 'react'
import PropTypes from 'prop-types'
import './index.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import moment from "moment";
import {Redirect} from "react-router-dom";
import swal from 'sweetalert';
import axios from "axios";
import {API_HOST} from "../../../constants";


class EventDetails extends React.Component {

    state = {
            redirect: false,
    };

    setRedirect = () => {
            this.setState({
                    redirect: true
            });
    };

    renderRedirect = () => {
            if (this.state.redirect) {
                    return <Redirect to='/Calendar/index'/>
            }
    };

    deletePopUp = () => {
            swal({
                            title: "Diesen Termin wirklich löschen?",

                            text: "Diesen Termin wird dauerhaft gelöscht. Diese Aktion kann nicht rückgängig gemacht werden.",

                            buttons: {
                                    cancel: "Abbrechen",
                                    confirm: {
                                            text: "Ja, Termin löschen",
                                            className: "swal-button--confirm_red",
                                            visible: true,
                                            value: "confirm",
                                    },
                            },
                    },
            ).then(async (value) => {
                    switch (value) {
                            case "confirm":
                                    const token = localStorage.getItem('accessToken');
                                    await axios.delete(`${API_HOST}/events/${this.props.eventId}/`, {
                                            headers: {
                                                    'authorization': `Bearer ${this.props.token}`
                                            }
                                    });
                                    this.setRedirect();
                                    break;

                            default:
                            //do nothing : we cancel and just go back to the page
                    }
            })
        }
    render() {
        //TODO this might need fixing, after the backend switched event types to be strings and no longer numbers
        const mapComponentToCategoryName = {
            andere: Medezinisch,  //hmmm looks like they all might be the same..  not sure yet // Medezinisch and Trainings and Other are displayed the same
            trainings: Medezinisch,  //hmmm looks like they all might be the same..  not sure yet // Medezinisch and Trainings and Other are displayed the same
            tests: Medezinisch,  //hmmm looks like they all might be the same..  not sure yet // Medezinisch and Trainings and Other are displayed the same
            medizinisch: Medezinisch, //hmmm looks like they all might be the same..  not sure yet // Medezinisch and Trainings and Other are displayed the same
            spiele: Medezinisch, //hmmm looks like they all might be the same..  not sure yet // Medezinisch and Trainings and Other are displayed the same
        }

        const { mainCategory } = this.props.event.mainCategory
        let Child =  mapComponentToCategoryName[mainCategory]

        if(!Child) {
            Child = Medezinisch
        }

        return (
            <section className={`event-details`}>
                <section className='event-details-top-section' >
                    <div className='control-buttons'>
                        <div className='control-button-container'>
                            <FontAwesomeIcon onClick={this.props.editEvent} className='edit-event-icon' size="1x" icon={['fal', 'pen']} />
                            <span className='primary-font-color'>Termin bearbeiten</span>
                        </div>
                        <div className='control-button-container'>
                            <FontAwesomeIcon onClick={this.deletePopUp} className='edit-event-icon' size="1x" icon={['fal', 'trash-alt']} />
                            <span onClick={this.deletePopUp} className='primary-font-color'>Termin löschen</span>
                        </div>
                    </div>
                    <section className='event-details-info-section'>
                        {Child && Child(this.props.event)}
                    </section>

                    <section className='event-details-attendance-buttons'>
                        <button onClick={() => alert('you clicked Du hast zu gesagt')}>
                            <FontAwesomeIcon onClick={this.props.editEvent} className='edit-event-icon' size="1x" icon={['fal', 'check']} />
                            <span>Du hast zu gesagt</span>
                        </button>
                        <button onClick={() => alert('you clicked Absagen')}>
                            <FontAwesomeIcon onClick={this.props.editEvent} className='edit-event-icon' size="1x" icon={['fal', 'times']} />
                            <span>Absagen</span>
                        </button>
                    </section>
                </section>
            </section>
        )
    }
}
EventDetails.propTypes = {
    editEvent: PropTypes.func.isRequired,
    event: PropTypes.object.isRequired,
}

const Trainings = () => {
    return (
        <div>
            <span>event1 Trainings</span>
        </div>
        )
}
const Medezinisch = (event) => {
    return (
        <React.Fragment>
            <div className='event-details-info-section--item'>
                <span className='item-title primary-font-color'>Datum</span>
                <span className='item-value secondary-font-color'>{moment(event.start).format('D. MMMM YYYY')}</span>
            </div>
            <div className='event-details-info-section--item'>
                <span className='item-title primary-font-color'>Zeit</span>
                <span className='item-value secondary-font-color'>{moment(event.start).format('HH:mm') + ' - ' + moment(event.end).format('HH:mm') }</span>
            </div>
            <div className='event-details-info-section--item'>
                <span className='item-title primary-font-color'>Ort</span>
                <span className='item-value secondary-font-color'>{event.place}</span>
            </div>
            <div className='event-details-info-section--item'>
                <span className='item-title primary-font-color'>Notizen</span>
                <span className='item-value secondary-font-color'>{event.description}</span>
            </div>
        </React.Fragment>
        )
}
const Spiele = () => {
    return (
        <div>
            <span>event6 Spiele</span>
        </div>
        )
}
const Tests = () => {
    return (
        <div>
            <span>event2 Tests</span>
        </div>
        )
}
const Andere = () => {
    return (
        <div>
            <span>event0 Andere</span>
        </div>
        )
}

export default EventDetails

constants.js

import { history } from './util/history'

export const API_HOST = process.env.REACT_APP_USE_STAGING_API ? "http://localhost:3000"
export const EVENTS_LIST_URL = `${API_HOST}/events/`

permissions.py

import operator
from functools import reduce

# Pip Modules
from rest_framework import permissions

# Django Modules
from django.db.models import Q
from django.contrib.auth.models import User, AnonymousUser

# Local Modules
from .models import BlindsideUser, BlindsideUserInTeam
from api.permissions.models import ClubPermission
from api.utils.resources.choices import roles, ACTION_PERMISSION_MAP, REQUEST_PERMISSION_MAP

class IsAdmin(permissions.BasePermission):
    """
        Admin Permission Group
        Only user with the Admin role(Club or Team)
        has access to this permission group
    """
    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        return BlindsideUserInTeam.objects.filter(role__contains='Admin', blindside_user=request.user).exists() \
            or BlindsideUser.objects.filter(role__contains='Admin', user=request.user).exists()


class IsManager(permissions.BasePermission):
    """
        Manager Permission Group
        Only user with the Manager role(Club or Team)
        has access to this permission group
    """
    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        return BlindsideUserInTeam.objects.filter(role__contains='Manager', blindside_user=request.user).exists() \
            or BlindsideUser.objects.filter(role__contains='Manager', user=request.user).exists()


class IsAthlete(permissions.BasePermission):
    """
        Athlete Permission Group
        Only user with the Athlete role(Club or Team)
        has access to this permission group
    """
    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        return BlindsideUserInTeam.objects.filter(role__contains='Athlete', blindside_user=request.user).exists() \
            or BlindsideUser.objects.filter(role__contains='Athlete', user=request.user).exists()


class IsStaff(permissions.BasePermission):
    """
        Staff Permission Group
        user with other roles(Club or Team)
        Asides Admin, Manager and Athlete
        has access to this permission group
    """
    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        return BlindsideUserInTeam.objects.filter(reduce(operator.and_, (Q(role__contains=role) for role in roles)),
                                                  blindside_user=request.user).exists() \
            or BlindsideUser.objects.filter(reduce(operator.and_, (Q(role__contains=role) for role in roles)),
                                            user=request.user).exists()


class HasClubPermissions(permissions.BasePermission):
    """
        Club Permission Group
        user with permission of view, edit, 
        add, delete a record, that is  attached
        to the club(e.g. exercise), will have access
        to this group
    """
    def get_action(self, view, request):
        action = REQUEST_PERMISSION_MAP.get(request.method)
        if view.action:
            action = ACTION_PERMISSION_MAP.get(view.action)

        return action + "-" + \
                            view.__class__.serializer_class.Meta.model.__name__.lower()


    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False

        club_id = request.data.get("club")
        if club_id:
            return self.get_action(view, request) in request.user.get_permissions()

general.py

from django.http import JsonResponse
from rest_framework import generics, viewsets, status

from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.authentication import JWTAuthentication


from api.users.models import BlindsideUser
from api.clubs.models import Team
from api.events.models.general import Event, EventTemplate, Attendance, UserCalendarPermission
from api.events.serializers.competition import MatchSerializer
from api.events.serializers.general import (AttendanceSerializer, EventTemplateSerializer, 
                                            EventSerializer, CalendarSerializer,
                                            UserCalendarSerializer, UserEventSerializer,
                                            TeamCalendarSerializer)
from api.utils.functions.fixtures import create_attendance_summary
from api.utils.resources.choices import choice_map


class EventListCreate(generics.ListCreateAPIView):
    """
    EventList returns a list of events upon making a GET request and create an Event upon make a POST request.

    Query params
    - start_date
    - end_date
    - user_id: return list of events of user_id
    - team_id: return list of events of users who are in team_id

    if user_id and team_id are not present then return event list of current logged in user
    """
    serializer_class = EventSerializer
    permission_classes = (IsAuthenticated,)
    queryset = Event.objects.all().select_subclasses().order_by('datetime')

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()

        def create_response(events):
            data = []
            for event in events:
                if event.event_type == 6:  # Match event
                    data.append(MatchSerializer(event).data)
                else:
                    data.append(EventSerializer(event).data)
            return data

        page = self.paginate_queryset(queryset)
        if page is not None:
            return_data = create_response(page)
            return self.get_paginated_response(return_data)

        return_data = create_response(queryset)
        return Response(return_data, status=status.HTTP_200_OK)

    def get_queryset(self):
        queryset = self.queryset
        query_params = self.request.GET

        if query_params.get('start_date'):
            queryset = queryset.filter(datetime__date__gte=query_params.get('start_date'))

        if query_params.get('end_date'):
            queryset = queryset.filter(datetime__date__lte=query_params.get('end_date'))

        if query_params.get('user_id'):
            return queryset.filter(attendance__attendant_id=query_params.get('user_id'))

        elif query_params.get('team_id'):
            team_users = BlindsideUser.objects.filter(blindside_user_in_team__team_id=query_params.get('team_id'))
            return queryset.filter(attendance__attendant__in=team_users)

        else:
            return queryset.filter(attendance__attendant=self.request.user)


class EventDetail(generics.RetrieveUpdateDestroyAPIView):
    """
    EventDetail is endpoint to retrieve or delete a particular event.

    :returns:
        - GET request       --  Retrieve details of event with primary key `pk`
        - DELETE request    --  Delete event with primary key `pk`
    """
    serializer_class = EventSerializer
    permission_classes = (IsAuthenticated,)
    queryset = Event.objects.all().select_subclasses()

    def get_serializer(self, *args, **kwargs):
        if self.request is None:
            return JsonResponse({'error': 'Request not found.'}, status=status.HTTP_400_BAD_REQUEST)
        if self.request.method == "GET":
            if args[0].event_type == 6:
                return MatchSerializer(args[0])
            return EventSerializer(args[0])
        if self.request.method == "PUT":
            return EventSerializer(args[0], data=kwargs['data'])

    def delete(self, request, *args, **kwargs):
        if not (request.user.is_club_admin() or request.user.is_superuser or request.user.is_staff):
            return JsonResponse({'error': 'User doesn\'t have access to this event'}, status=status.HTTP_401_UNAUTHORIZED)
        try:
            event_obj = self.queryset.get(pk=kwargs['pk'])
        except Event.DoesNotExist:
            # TODO: Raise a 404 maybe instead of a normal exception?
            raise NotFound('Event with id: {} doesn\'t exists.'.format(kwargs['pk']))

        if event_obj.deleted_at is not None:
            return JsonResponse({'error': 'Event is already deleted.'}, status=status.HTTP_400_BAD_REQUEST)
        event_obj.delete()  # Event Model inherits SoftDeletionModel => delete will only soft delete the instance
        return JsonResponse(
            {
                'type': 'delete',
                'message': 'Event has been deleted.'
            },
            status=status.HTTP_204_NO_CONTENT
        )


class AttendanceViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for viewing, editing(updating), listing and deleting the attendance
    of an user in an event.
    """
    permission_classes = (IsAuthenticated,)
    authentication_classes = (JWTAuthentication,)
    serializer_class = AttendanceSerializer
    queryset = Attendance.objects.all()

    def get_queryset(self):
        return self.queryset.filter(event_id=self.kwargs['event_id'])

    def list(self, request, *args, **kwargs):
        return Response(data=create_attendance_summary(self.get_queryset()), status=status.HTTP_200_OK)

    def retrieve(self, request, *args, **kwargs):
        if not self.check_attendant_exists():
            return Response({
                'error': 'No such attendant to this event is present.'
            }, status=status.HTTP_204_NO_CONTENT)

        data = self.serializer_class(self.get_queryset().get(id=kwargs['pk'])).data
        return Response(data=data, status=status.HTTP_200_OK)

    # Note: No need to implement since these objects are
    # automatically created when the event is created
    # def create(self, request, *args, **kwargs):
    #     pass

    def update(self, request, *args, **kwargs):
        if not self.check_attendant_exists():
            return Response({
                'error': 'No such attendant to this event is present.'
            }, status=status.HTTP_204_NO_CONTENT)

        attendance_instance = self.get_queryset().filter(id=kwargs['pk']).first()
        update_data = self.request.data

        if update_data.get('attending', None) is 2 and update_data.get('reason', None) is None:
            return Response({
                'error': 'User can\'t reject event invitation without providing a reason'
            }, status=status.HTTP_400_BAD_REQUEST)

        serializer = self.serializer_class(
            instance=attendance_instance,
            data=update_data,
            partial=True
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def destroy(self, request, *args, **kwargs):
        if not self.check_attendant_exists():
            return Response({
                'error': 'No such attendant to this event is present'
            }, status=status.HTTP_204_NO_CONTENT)

        attendance_instance = self.get_queryset().filter(id=kwargs['pk']).first()
        attendance_instance.delete()

        return Response({'type': 'delete'}, status=status.HTTP_204_NO_CONTENT)

    def check_attendant_exists(self):
        return self.get_queryset().filter(id=self.kwargs['pk']).exists()


class EventTemplateList(generics.ListCreateAPIView):
    serializer_class = EventTemplateSerializer
    queryset = EventTemplate.objects.all()


class EventTemplateDetail(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = EventTemplateSerializer


class UserEventsViewSet(viewsets.ModelViewSet):
    """
        GET: Retrieve list of users events
    """
    queryset = Event.objects.all()
    serializer_class = UserEventSerializer
    authentication_classes = (JWTAuthentication,)
    permission_classes = (IsAuthenticated, )

    def get_queryset(self):
        return self.queryset.filter(participants__id=self.request.user.id)

    def filter_queryset(self, queryset):
        """
            Applying extra query filters

            filters:
            - start_date: to get events after the date
            - end date: to get events before the date
        """
        query_params = self.request.GET
        queryset = self.get_queryset()

        if query_params.get('start_date'):
            queryset = queryset.filter(datetime__date__gte=query_params.get('start_date'))

        if query_params.get('end_date'):
            queryset = queryset.filter(datetime__date__lte=query_params.get('end_date'))

        return queryset


class CalendarViewSet(viewsets.ModelViewSet):
    """
        Simple viewset to manage calendar subscriptions

        GET: get list of all member in my club with info if I subscribed 
                to them or not
        POST: subscribe calendar to that user
    """
    serializer_class = CalendarSerializer

    def get_queryset(self):
        return UserCalendarPermission.objects.filter(user=self.request.user)

    def list(self, request, *args, **kwargs):
        """
            Return all club members in my club with info of user 
            has subscribed to calendar or not
        """
        subscribed_users = [subscription_info.target_user.id for subscription_info
                            in self.get_queryset().filter(target_team=None)]
        club_users = BlindsideUser.objects.filter(
                            clubs=self.request.user.clubs
                        )

        club_users_data = UserCalendarSerializer(club_users, many=True).data

        for data in club_users_data:
            data['is_subscribed'] = data.get('id') in subscribed_users

            roles = dict()
            for role in data['role']:
                roles[role] = choice_map['club_roles'][int(role)][1]
            data['role'] = roles

            teams = dict()
            for team in data['teams']:
                # TODO Change the serializer to TeamDetail has errors in implementation
                teams[str(team)] = TeamCalendarSerializer(Team.objects.get(id=team)).data
            data['teams'] = teams

        subscribed_teams = [subscription_info.target_team.id for subscription_info
                            in self.get_queryset().filter(target_user=None)]

        if request.user.is_club_admin():
            club_teams = Team.objects.filter(club=request.user.clubs)
        else:
            club_teams = request.user.teams.all()

        club_teams_data = TeamCalendarSerializer(club_teams, many=True).data

        for data in club_teams_data:
            data['is_subscribed'] = data.get('id') in subscribed_teams

        return Response({
            "users": club_users_data,
            "teams": club_teams_data
        })

    def create(self, request, *args, **kwargs):
        if self.request.data.get('target_team') and self.get_queryset().filter(target_team_id=self.request.data.get('target_team')).exists() or \
                self.request.data.get('target_user') and self.get_queryset().filter(target_user_id=self.request.data.get('target_user')):
            return Response({'error': 'Subscription already exists'}, status=status.HTTP_400_BAD_REQUEST)

        from copy import deepcopy
        request_data = deepcopy(request.data)
        request_data['user'] = request.user.id

        serializer = self.serializer_class(data=request_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(data=serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=['delete'])
    def delete(self, request, *args, **kwargs):
        obj = self.get_object()
        if not obj:
            raise NotFound("No object found")

        obj.delete()
        return Response({}, status=status.HTTP_204_NO_CONTENT)

    def get_object(self):
        if self.request.data.get('target_team'):
            return self.get_queryset().get(user=self.request.user, target_team_id=self.request.data.get('target_team'))

        if self.request.data.get('target_user'):
            return self.get_queryset().get(user=self.request.user, target_user_id=self.request.data.get('target_user'))

test_views.py

 def test_deleting_exercise(self):
+        self.user.is_superuser = True
+        self.user.save()
         response = self.client.delete(reverse('events:exercise-detail', kwargs={'pk': self.exercise.id}),
                                       HTTP_AUTHORIZATION='Bearer ' + self.user.token, format='json'
                                       )

1 个答案:

答案 0 :(得分:0)

您要从localStorage提取访问令牌,然后不使用它?也许您发送的令牌错误,或者如果this.props.token未定义,则根本没有令牌?

    report = open(file_name, 'rb')
    response = HttpResponse(FileWrapper(report), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = 'attachment; filename='Report.xlsx'
    return response