当尝试通过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'
)
答案 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