From patchwork Fri Apr 15 18:24:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Doan X-Patchwork-Id: 611113 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qmmGk5xq7z9t3n for ; Sat, 16 Apr 2016 04:27:10 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b=XiHXievn; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3qmmGk42kWzDq62 for ; Sat, 16 Apr 2016 04:27:10 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b=XiHXievn; dkim-atps=neutral X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Received: from mail-oi0-x232.google.com (mail-oi0-x232.google.com [IPv6:2607:f8b0:4003:c06::232]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3qmmF53029zDq9q for ; Sat, 16 Apr 2016 04:25:45 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b=XiHXievn; dkim-atps=neutral Received: by mail-oi0-x232.google.com with SMTP id p188so132036665oih.2 for ; Fri, 15 Apr 2016 11:25:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zewpEORgoydZB0vsYC/mIK90+hAueGmptcM1qxZOhJY=; b=XiHXievnEN4vF6uUD54yPbhUDvg4z+IXphGIUL5L9YlR8Ei0xiXTFV5Pp35L8NaP4f pGqkRuKeysJPeFUdxaLtSrLrvv7VRL3ysUtUY7AZytv40xST7FvQT5C4bf2bwWaey5a7 ADG2Lz3GX5A1LCHs3CjIB3WACrYdb7UMMnc7g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zewpEORgoydZB0vsYC/mIK90+hAueGmptcM1qxZOhJY=; b=AwbfMkQxk/Kv2Jrp8ib1K94KsZka9g7JOQSa3B3GXJrl8xohj5O8T2CVxJnK/A5/tc 9HQdZQiBQHrUwc0rjmytwL08yzIT6oo2z5O9VrQaMCgZTYItFd8Y/HAK8bIJc3ZDUUbs LbXHMEE1zi/YDZRq1z/NZsB5U9bRCYqro9+Bo1/fH0uvfiHD3zRuZ2WZNn9927IbGED+ p28OEA5jMuzhqvrERLiS7dLUSaEHwS13zv4Hls75GnilktVmLRN787wJt3SzXRzyLIVA uei632Q/7ohBj5+19aFeWhvegn2j/qlEM/q+N1fUnzSJTrMW1JyRdVGF1NrG/StMzc9D Knxw== X-Gm-Message-State: AOPr4FW6PHQk32AvR6m6epwadupaoIC5N/zhzBgQfa3GjLKrPh0w9A+lDCEn2yzu2FooLIG/ X-Received: by 10.202.87.143 with SMTP id l137mr10872024oib.89.1460744743103; Fri, 15 Apr 2016 11:25:43 -0700 (PDT) Received: from doanac-xps.local (cpe-70-117-126-139.austin.res.rr.com. [70.117.126.139]) by smtp.gmail.com with ESMTPSA id n6sm15322610obi.4.2016.04.15.11.25.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 15 Apr 2016 11:25:42 -0700 (PDT) From: Andy Doan To: patchwork@lists.ozlabs.org Subject: [RFC 05/11] REST: Add Persons to the API Date: Fri, 15 Apr 2016 13:24:01 -0500 Message-Id: <1460744647-9729-6-git-send-email-andy.doan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1460744647-9729-1-git-send-email-andy.doan@linaro.org> References: <1460744647-9729-1-git-send-email-andy.doan@linaro.org> X-BeenThere: patchwork@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Patchwork development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" This exports person objects via the REST API. Security Constraints: * The API is read-only to authenticated users Signed-off-by: Andy Doan --- patchwork/tests/test_rest_api.py | 36 ++++++++++++++++++++++++++++++++++++ patchwork/views/rest_api.py | 14 +++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/patchwork/tests/test_rest_api.py b/patchwork/tests/test_rest_api.py index 6f2f988..76f0c12 100644 --- a/patchwork/tests/test_rest_api.py +++ b/patchwork/tests/test_rest_api.py @@ -106,3 +106,39 @@ class TestProjectAPI(APITestCase): resp = self.client.delete('/api/1.0/projects/1/') self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) self.assertEqual(1, Project.objects.all().count()) + + +@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API') +class TestPersonAPI(APITestCase): + fixtures = ['default_states'] + + def test_anonymous_list(self): + """The API should reject anonymous users.""" + resp = self.client.get('/api/1.0/people/') + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_authenticated_list(self): + """This API requires authenticated users.""" + user = create_user() + self.client.force_authenticate(user=user) + resp = self.client.get('/api/1.0/people/') + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(1, resp.data['count']) + self.assertEqual(user.username, resp.data['results'][0]['name']) + self.assertEqual(user.email, resp.data['results'][0]['email']) + + def test_readonly(self): + defaults.project.save() + user = create_maintainer(defaults.project) + user.is_superuser = True + user.save() + self.client.force_authenticate(user=user) + + resp = self.client.delete('/api/1.0/people/1/') + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + resp = self.client.patch('/api/1.0/people/1/', {'email': 'foo@f.com'}) + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + resp = self.client.post('/api/1.0/people/', {'email': 'foo@f.com'}) + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) diff --git a/patchwork/views/rest_api.py b/patchwork/views/rest_api.py index f6385a3..ab576cc 100644 --- a/patchwork/views/rest_api.py +++ b/patchwork/views/rest_api.py @@ -19,7 +19,7 @@ from django.conf.urls import url, include -from patchwork.models import Project +from patchwork.models import Person, Project from rest_framework import permissions from rest_framework.pagination import PageNumberPagination @@ -48,6 +48,12 @@ class PatchworkPermission(permissions.BasePermission): return obj.is_editable(request.user) +class AuthenticatedReadOnly(permissions.BasePermission): + def has_permission(self, request, view): + authenticated = request.user.is_authenticated() + return authenticated and request.method in permissions.SAFE_METHODS + + class PatchworkViewSet(ModelViewSet): pagination_class = PageSizePagination @@ -62,12 +68,18 @@ def create_model_serializer(model_class): return PatchworkSerializer +class PeopleViewSet(PatchworkViewSet): + permission_classes = (AuthenticatedReadOnly,) + serializer_class = create_model_serializer(Person) + + class ProjectViewSet(PatchworkViewSet): permission_classes = (PatchworkPermission,) serializer_class = create_model_serializer(Project) router = DefaultRouter() +router.register('people', PeopleViewSet, 'person') router.register('projects', ProjectViewSet, 'project') urlpatterns = [