Skip to content

Commit c8592fb

Browse files
committed
Merge branch 'master' into stsewd/update-pytest
2 parents d4eeb1a + c6c918e commit c8592fb

File tree

4 files changed

+90
-87
lines changed

4 files changed

+90
-87
lines changed

readthedocs/api/v2/urls.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
BuildCommandViewSet,
1818
BuildViewSet,
1919
DomainViewSet,
20-
NotificationViewSet,
2120
ProjectViewSet,
2221
RemoteOrganizationViewSet,
2322
RemoteRepositoryViewSet,
@@ -31,7 +30,6 @@
3130
router.register(r'command', BuildCommandViewSet, basename='buildcommandresult')
3231
router.register(r'version', VersionViewSet, basename='version')
3332
router.register(r'project', ProjectViewSet, basename='project')
34-
router.register(r'notification', NotificationViewSet, basename='emailhook')
3533
router.register(r'domain', DomainViewSet, basename='domain')
3634
router.register(r'sphinx_domain', SphinxDomainAPIView, basename='sphinxdomain')
3735
router.register(

readthedocs/api/v2/views/model_views.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,6 @@ class BuildCommandViewSet(UserSelectViewSet):
292292
model = BuildCommandResult
293293

294294

295-
class NotificationViewSet(viewsets.ReadOnlyModelViewSet):
296-
permission_classes = (permissions.IsAuthenticated, RelatedProjectIsOwner)
297-
renderer_classes = (JSONRenderer,)
298-
model = EmailHook
299-
300-
def get_queryset(self):
301-
return self.model.objects.api(self.request.user)
302-
303-
304295
class DomainViewSet(UserSelectViewSet):
305296
permission_classes = [APIRestrictedPermission]
306297
renderer_classes = (JSONRenderer,)

readthedocs/projects/urls/private.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
ProjectAdvertisingUpdate,
2828
ProjectDashboard,
2929
ProjectDelete,
30+
ProjectRedirects,
31+
ProjectRedirectsDelete,
3032
ProjectUpdate,
33+
ProjectUsersCreateList,
34+
ProjectUsersDelete,
3135
)
3236

3337

@@ -74,12 +78,14 @@
7478
name='projects_delete',
7579
),
7680
url(
77-
r'^(?P<project_slug>[-\w]+)/users/$', private.project_users,
81+
r'^(?P<project_slug>[-\w]+)/users/$',
82+
ProjectUsersCreateList.as_view(),
7883
name='projects_users',
7984
),
8085
url(
8186
r'^(?P<project_slug>[-\w]+)/users/delete/$',
82-
private.project_users_delete, name='projects_users_delete',
87+
ProjectUsersDelete.as_view(),
88+
name='projects_users_delete',
8389
),
8490
url(
8591
r'^(?P<project_slug>[-\w]+)/notifications/$',
@@ -99,12 +105,14 @@
99105
name='projects_translations_delete',
100106
),
101107
url(
102-
r'^(?P<project_slug>[-\w]+)/redirects/$', private.project_redirects,
108+
r'^(?P<project_slug>[-\w]+)/redirects/$',
109+
ProjectRedirects.as_view(),
103110
name='projects_redirects',
104111
),
105112
url(
106113
r'^(?P<project_slug>[-\w]+)/redirects/delete/$',
107-
private.project_redirects_delete, name='projects_redirects_delete',
114+
ProjectRedirectsDelete.as_view(),
115+
name='projects_redirects_delete',
108116
),
109117
url(
110118
r'^(?P<project_slug>[-\w]+)/advertising/$',

readthedocs/projects/views/private.py

Lines changed: 78 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from django.conf import settings
88
from django.contrib import messages
99
from django.contrib.auth.decorators import login_required
10-
from django.contrib.auth.models import User
1110
from django.db.models import Count
1211
from django.http import (
1312
Http404,
@@ -24,7 +23,14 @@
2423
from django.utils.translation import ugettext_lazy as _
2524
from django.views.generic import ListView, TemplateView, View
2625
from formtools.wizard.views import SessionWizardView
27-
from vanilla import CreateView, DeleteView, DetailView, GenericView, UpdateView
26+
from vanilla import (
27+
CreateView,
28+
DeleteView,
29+
DetailView,
30+
FormView,
31+
GenericView,
32+
UpdateView,
33+
)
2834

2935
from readthedocs.builds.forms import VersionForm
3036
from readthedocs.builds.models import Version
@@ -445,47 +451,49 @@ class ProjectRelationshipDelete(ProjectRelationshipMixin, DeleteView):
445451
http_method_names = ['post']
446452

447453

448-
@login_required
449-
def project_users(request, project_slug):
450-
"""Project users view and form view."""
451-
project = get_object_or_404(
452-
Project.objects.for_admin_user(request.user),
453-
slug=project_slug,
454-
)
454+
class ProjectUsersMixin(ProjectAdminMixin, PrivateViewMixin):
455455

456-
form = UserForm(data=request.POST or None, project=project)
456+
form_class = UserForm
457457

458-
if request.method == 'POST' and form.is_valid():
458+
def get_queryset(self):
459+
project = self.get_project()
460+
return project.users.all()
461+
462+
def get_success_url(self):
463+
return reverse('projects_users', args=[self.get_project().slug])
464+
465+
466+
class ProjectUsersCreateList(ProjectUsersMixin, FormView):
467+
468+
template_name = 'projects/project_users.html'
469+
470+
def form_valid(self, form):
459471
form.save()
460-
project_dashboard = reverse('projects_users', args=[project.slug])
461-
return HttpResponseRedirect(project_dashboard)
472+
return HttpResponseRedirect(self.get_success_url())
462473

463-
users = project.users.all()
474+
def get_context_data(self, **kwargs):
475+
context = super().get_context_data(**kwargs)
476+
context['users'] = self.get_queryset()
477+
return context
464478

465-
return render(
466-
request,
467-
'projects/project_users.html',
468-
{'form': form, 'project': project, 'users': users},
469-
)
470479

480+
class ProjectUsersDelete(ProjectUsersMixin, GenericView):
471481

472-
@login_required
473-
def project_users_delete(request, project_slug):
474-
if request.method != 'POST':
475-
return HttpResponseNotAllowed('Only POST is allowed')
476-
project = get_object_or_404(
477-
Project.objects.for_admin_user(request.user),
478-
slug=project_slug,
479-
)
480-
user = get_object_or_404(
481-
User.objects.all(),
482-
username=request.POST.get('username'),
483-
)
484-
if user == request.user:
485-
raise Http404
486-
project.users.remove(user)
487-
project_dashboard = reverse('projects_users', args=[project.slug])
488-
return HttpResponseRedirect(project_dashboard)
482+
http_method_names = ['post']
483+
484+
def post(self, request, *args, **kwargs):
485+
username = self.request.POST.get('username')
486+
user = get_object_or_404(
487+
self.get_queryset(),
488+
username=username,
489+
)
490+
if user == request.user:
491+
raise Http404
492+
493+
project = self.get_project()
494+
project.users.remove(user)
495+
496+
return HttpResponseRedirect(self.get_success_url())
489497

490498

491499
@login_required
@@ -598,50 +606,48 @@ def project_translations_delete(request, project_slug, child_slug):
598606
return HttpResponseRedirect(project_dashboard)
599607

600608

601-
@login_required
602-
def project_redirects(request, project_slug):
609+
class ProjectRedirectsMixin(ProjectAdminMixin, PrivateViewMixin):
610+
603611
"""Project redirects view and form view."""
604-
project = get_object_or_404(
605-
Project.objects.for_admin_user(request.user),
606-
slug=project_slug,
607-
)
608612

609-
form = RedirectForm(data=request.POST or None, project=project)
613+
def get_success_url(self):
614+
return reverse(
615+
'projects_redirects',
616+
args=[self.get_project().slug],
617+
)
610618

611-
if request.method == 'POST' and form.is_valid():
619+
620+
class ProjectRedirects(ProjectRedirectsMixin, FormView):
621+
622+
form_class = RedirectForm
623+
template_name = 'projects/project_redirects.html'
624+
625+
def form_valid(self, form):
612626
form.save()
613-
project_dashboard = reverse('projects_redirects', args=[project.slug])
614-
return HttpResponseRedirect(project_dashboard)
627+
return HttpResponseRedirect(self.get_success_url())
615628

616-
redirects = project.redirects.all()
629+
def get_context_data(self, **kwargs):
630+
context = super().get_context_data(**kwargs)
631+
project = self.get_project()
632+
context['redirects'] = project.redirects.all()
633+
return context
617634

618-
return render(
619-
request,
620-
'projects/project_redirects.html',
621-
{'form': form, 'project': project, 'redirects': redirects},
622-
)
623635

636+
class ProjectRedirectsDelete(ProjectRedirectsMixin, GenericView):
624637

625-
@login_required
626-
def project_redirects_delete(request, project_slug):
627-
"""Project redirect delete view."""
628-
if request.method != 'POST':
629-
return HttpResponseNotAllowed('Only POST is allowed')
630-
project = get_object_or_404(
631-
Project.objects.for_admin_user(request.user),
632-
slug=project_slug,
633-
)
634-
redirect = get_object_or_404(
635-
project.redirects,
636-
pk=request.POST.get('id_pk'),
637-
)
638-
if redirect.project == project:
639-
redirect.delete()
640-
else:
641-
raise Http404
642-
return HttpResponseRedirect(
643-
reverse('projects_redirects', args=[project.slug]),
644-
)
638+
http_method_names = ['post']
639+
640+
def post(self, request, *args, **kwargs):
641+
project = self.get_project()
642+
redirect = get_object_or_404(
643+
project.redirects,
644+
pk=request.POST.get('id_pk'),
645+
)
646+
if redirect.project == project:
647+
redirect.delete()
648+
else:
649+
raise Http404
650+
return HttpResponseRedirect(self.get_success_url())
645651

646652

647653
@login_required

0 commit comments

Comments
 (0)