diff --git a/greenmine/base/api_actions.py b/greenmine/base/api_actions.py deleted file mode 100644 index 4dab26a9..00000000 --- a/greenmine/base/api_actions.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -import datetime -import json - -from django.core.serializers.json import DjangoJSONEncoder -from django.views.generic.base import View -from django.views.decorators.csrf import csrf_exempt -from django.contrib.auth import logout, login, authenticate -from django.contrib.auth.models import User -from django.utils.functional import Promise -from django.utils.encoding import force_text -from django.utils.decorators import method_decorator -from django.utils import timezone -from django import http - - -class LazyEncoder(DjangoJSONEncoder): - """ - JSON encoder class for encode correctly traduction strings. - Is for ajax response encode. - """ - - def default(self, obj): - if isinstance(obj, Promise): - return force_text(obj) - elif isinstance(obj, datetime.datetime): - obj = timezone.localtime(obj) - return super(LazyEncoder, self).default(obj) - - -def request_json_to_dict(request): - try: - body = request.body.decode('utf-8') - return json.loads(body) - except Exception: - return {} - - -def to_json(data): - return json.dumps(data) - - -class Login(View): - def post(self, request): - data = request_json_to_dict(request) - - username = data.get('username', None) - password = data.get('password', None) - - try: - user = User.objects.get(username=username) - if user.check_password(password): - user = authenticate(username=username, password=password) - login(request, user) - return http.HttpResponse(to_json({'token': request.session.session_key})) - except User.DoesNotExist: - pass - - return http.HttpResponseBadRequest() - - @method_decorator(csrf_exempt) - def dispatch(self, *args, **kwargs): - return super(Login, self).dispatch(*args, **kwargs) - - -class Logout(View): - def post(self, request): - logout(request) - return HttpResponse() - - @method_decorator(csrf_exempt) - def dispatch(self, *args, **kwargs): - return super(Login, self).dispatch(*args, **kwargs) diff --git a/greenmine/base/views.py b/greenmine/base/views.py new file mode 100644 index 00000000..ebc972b9 --- /dev/null +++ b/greenmine/base/views.py @@ -0,0 +1,23 @@ +from rest_framework import renderers +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.reverse import reverse + + +@api_view(('GET',)) +def api_root(request, format=None): + return Response({ + 'projects': reverse('project-list', request=request, format=format), + 'milestones': reverse('milestone-list', request=request, format=format), + 'user-stories': reverse('user-story-list', request=request, format=format), + 'changes': reverse('change-list', request=request, format=format), + 'change-attachments': reverse('change-attachment-list', request=request, format=format), + 'tasks': reverse('task-list', request=request, format=format), + 'severities': reverse('severity-list', request=request, format=format), + 'issue-status': reverse('issue-status-list', request=request, format=format), + 'task-status': reverse('task-status-list', request=request, format=format), + 'user-story-status': reverse('user-story-status-list', request=request, format=format), + 'priorities': reverse('priority-list', request=request, format=format), + 'issue-types': reverse('issue-type-list', request=request, format=format), + 'points': reverse('points-list', request=request, format=format), + }) diff --git a/greenmine/scrum/api.py b/greenmine/scrum/api.py index 440bf6aa..7d7ceacc 100644 --- a/greenmine/scrum/api.py +++ b/greenmine/scrum/api.py @@ -1,115 +1,134 @@ -# myapp/api.py -from tastypie.resources import ModelResource -from tastypie.authentication import SessionAuthentication -from tastypie.authorization import DjangoAuthorization -from tastypie import fields +from rest_framework import generics -from greenmine.scrum import models +from greenmine.scrum.serializers import * +from greenmine.scrum.models import * -class ProjectResource(ModelResource): - class Meta: - queryset = models.Project.objects.all() - resource_name = 'project' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ProjectList(generics.ListCreateAPIView): + model = Project + serializer_class = ProjectSerializer -class MilestoneResource(ModelResource): - class Meta: - queryset = models.Milestone.objects.all() - resource_name = 'milestone' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ProjectDetail(generics.RetrieveUpdateDestroyAPIView): + model = Project + serializer_class = ProjectSerializer -class UserStoryResource(ModelResource): - class Meta: - queryset = models.UserStory.objects.all() - resource_name = 'userstory' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class MilestoneList(generics.ListCreateAPIView): + model = Milestone + serializer_class = MilestoneSerializer -class ChangeResource(ModelResource): - class Meta: - queryset = models.Change.objects.all() - resource_name = 'change' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class MilestoneDetail(generics.RetrieveUpdateDestroyAPIView): + model = Milestone + serializer_class = MilestoneSerializer -class ChangeAttachmentResource(ModelResource): - class Meta: - queryset = models.ChangeAttachment.objects.all() - resource_name = 'changeattachment' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class UserStoryList(generics.ListCreateAPIView): + model = UserStory + serializer_class = UserStorySerializer -class TaskResource(ModelResource): - class Meta: - queryset = models.Task.objects.all() - resource_name = 'task' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class UserStoryDetail(generics.RetrieveUpdateDestroyAPIView): + model = UserStory + serializer_class = UserStorySerializer -class SeverityResource(ModelResource): - class Meta: - queryset = models.Severity.objects.all() - resource_name = 'choices/severity' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ChangeList(generics.ListCreateAPIView): + model = Change + serializer_class = ChangeSerializer -class IssueStatusResource(ModelResource): - class Meta: - queryset = models.IssueStatus.objects.all() - resource_name = 'choices/issue-status' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() - -from tastypie.constants import ALL, ALL_WITH_RELATIONS - -class TaskStatusResource(ModelResource): - project = fields.ForeignKey(ProjectResource, 'project') - - class Meta: - queryset = models.TaskStatus.objects.all() - resource_name = 'choices/task-status' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() - filtering = { - "project": ALL_WITH_RELATIONS, - } - -class UserStoryStatusResource(ModelResource): - class Meta: - queryset = models.UserStoryStatus.objects.all() - resource_name = 'choices/us-status' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() - -class PriorityResource(ModelResource): - class Meta: - queryset = models.Priority.objects.all() - resource_name = 'choices/priority' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ChangeDetail(generics.RetrieveUpdateDestroyAPIView): + model = Change + serializer_class = ChangeSerializer -class IssueTypeResource(ModelResource): - class Meta: - queryset = models.IssueType.objects.all() - resource_name = 'choices/issue-type' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ChangeAttachmentList(generics.ListCreateAPIView): + model = ChangeAttachment + serializer_class = ChangeAttachmentSerializer -class PointsResource(ModelResource): - class Meta: - queryset = models.Points.objects.all() - resource_name = 'choices/story-points' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() +class ChangeAttachmentDetail(generics.RetrieveUpdateDestroyAPIView): + model = ChangeAttachment + serializer_class = ChangeAttachmentSerializer + + +class TaskList(generics.ListCreateAPIView): + model = Task + serializer_class = TaskSerializer + + +class TaskDetail(generics.RetrieveUpdateDestroyAPIView): + model = Task + serializer_class = TaskSerializer + + +class SeverityList(generics.ListCreateAPIView): + model = Severity + serializer_class = SeveritySerializer + + +class SeverityDetail(generics.RetrieveUpdateDestroyAPIView): + model = Severity + serializer_class = SeveritySerializer + + +class IssueStatusList(generics.ListCreateAPIView): + model = IssueStatus + serializer_class = IssueStatusSerializer + + +class IssueStatusDetail(generics.RetrieveUpdateDestroyAPIView): + model = IssueStatus + serializer_class = IssueStatusSerializer + + +class TaskStatusList(generics.ListCreateAPIView): + model = TaskStatus + serializer_class = TaskStatusSerializer + + +class TaskStatusDetail(generics.RetrieveUpdateDestroyAPIView): + model = TaskStatus + serializer_class = TaskStatusSerializer + + +class UserStoryStatusList(generics.ListCreateAPIView): + model = UserStoryStatus + serializer_class = UserStoryStatusSerializer + + +class UserStoryStatusDetail(generics.RetrieveUpdateDestroyAPIView): + model = UserStoryStatus + serializer_class = UserStoryStatusSerializer + + +class PriorityList(generics.ListCreateAPIView): + model = Priority + serializer_class = PrioritySerializer + + +class PriorityDetail(generics.RetrieveUpdateDestroyAPIView): + model = Priority + serializer_class = PrioritySerializer + + +class IssueTypeList(generics.ListCreateAPIView): + model = IssueType + serializer_class = IssueTypeSerializer + + +class IssueTypeDetail(generics.RetrieveUpdateDestroyAPIView): + model = IssueType + serializer_class = IssueTypeSerializer + + +class PointsList(generics.ListCreateAPIView): + model = Points + serializer_class = PointsSerializer + + +class PointsDetail(generics.RetrieveUpdateDestroyAPIView): + model = Points + serializer_class = PointsSerializer diff --git a/greenmine/scrum/serializers.py b/greenmine/scrum/serializers.py new file mode 100644 index 00000000..d766584d --- /dev/null +++ b/greenmine/scrum/serializers.py @@ -0,0 +1,80 @@ +from rest_framework import serializers + +from greenmine.scrum.models import * + +class ProjectSerializer(serializers.ModelSerializer): + class Meta: + model = Project + fields = () + + +class MilestoneSerializer(serializers.ModelSerializer): + class Meta: + model = Milestone + fields = () + + +class UserStorySerializer(serializers.ModelSerializer): + class Meta: + model = UserStory + fields = () + + +class ChangeSerializer(serializers.ModelSerializer): + class Meta: + model = Change + fields = () + + +class ChangeAttachmentSerializer(serializers.ModelSerializer): + class Meta: + model = ChangeAttachment + fields = () + + +class TaskSerializer(serializers.ModelSerializer): + class Meta: + model = Task + fields = () + + +class SeveritySerializer(serializers.ModelSerializer): + class Meta: + model = Severity + fields = () + + +class IssueStatusSerializer(serializers.ModelSerializer): + class Meta: + model = IssueStatus + fields = () + + +class TaskStatusSerializer(serializers.ModelSerializer): + class Meta: + model = TaskStatus + fields = () + + +class UserStoryStatusSerializer(serializers.ModelSerializer): + class Meta: + model = UserStoryStatus + fields = () + + +class PrioritySerializer(serializers.ModelSerializer): + class Meta: + model = Priority + fields = () + + +class IssueTypeSerializer(serializers.ModelSerializer): + class Meta: + model = IssueType + fields = () + + +class PointsSerializer(serializers.ModelSerializer): + class Meta: + model = Points + fields = () diff --git a/greenmine/scrum/urls.py b/greenmine/scrum/urls.py new file mode 100644 index 00000000..e01bece8 --- /dev/null +++ b/greenmine/scrum/urls.py @@ -0,0 +1,34 @@ +from django.conf.urls import patterns, url +from rest_framework.urlpatterns import format_suffix_patterns + +from greenmine.scrum import api + +urlpatterns = format_suffix_patterns(patterns('', + url(r'^projects/$', api.ProjectList.as_view(), name='project-list'), + url(r'^projects/(?P[0-9]+)/$', api.ProjectDetail.as_view(), name='project-detail'), + url(r'^milestones/$', api.MilestoneList.as_view(), name='milestone-list'), + url(r'^milestones/(?P[0-9]+)/$', api.MilestoneDetail.as_view(), name='milestone-detail'), + url(r'^user_stories/$', api.UserStoryList.as_view(), name='user-story-list'), + url(r'^user_stories/(?P[0-9]+)/$', api.UserStoryDetail.as_view(), name='user-story-detail'), + url(r'^changes/$', api.ChangeList.as_view(), name='change-list'), + url(r'^changes/(?P[0-9]+)/$', api.ChangeDetail.as_view(), name='change-detail'), + url(r'^change_attachments/$', api.ChangeAttachmentList.as_view(), name='change-attachment-list'), + url(r'^change_attachments/(?P[0-9]+)/$', api.ChangeAttachmentDetail.as_view(), name='change-attachment-detail'), + url(r'^tasks/$', api.TaskList.as_view(), name='task-list'), + url(r'^tasks/(?P[0-9]+)/$', api.TaskDetail.as_view(), name='task-detail'), + url(r'^severities/$', api.SeverityList.as_view(), name='severity-list'), + url(r'^severities/(?P[0-9]+)/$', api.SeverityDetail.as_view(), name='severity-detail'), + url(r'^issue_status/$', api.IssueStatusList.as_view(), name='issue-status-list'), + url(r'^issue_status/(?P[0-9]+)/$', api.IssueStatusDetail.as_view(), name='issue-status-detail'), + url(r'^task_status/$', api.TaskStatusList.as_view(), name='task-status-list'), + url(r'^task_status/(?P[0-9]+)/$', api.TaskStatusDetail.as_view(), name='task-status-detail'), + url(r'^user_story_status/$', api.UserStoryStatusList.as_view(), name='user-story-status-list'), + url(r'^user_story_status/(?P[0-9]+)/$', api.UserStoryStatusDetail.as_view(), name='user-story-status-detail'), + url(r'^priorities/$', api.PriorityList.as_view(), name='priority-list'), + url(r'^priorities/(?P[0-9]+)/$', api.PriorityDetail.as_view(), name='priority-detail'), + url(r'^issue_types/$', api.IssueTypeList.as_view(), name='issue-type-list'), + url(r'^issue_types/(?P[0-9]+)/$', api.IssueTypeDetail.as_view(), name='issue-type-detail'), + url(r'^points/$', api.PointsList.as_view(), name='points-list'), + url(r'^points/(?P[0-9]+)/$', api.PointsDetail.as_view(), name='points-detail'), +)) + diff --git a/greenmine/settings/common.py b/greenmine/settings/common.py index 1e8a39a9..fbbeccb4 100644 --- a/greenmine/settings/common.py +++ b/greenmine/settings/common.py @@ -213,6 +213,7 @@ INSTALLED_APPS = [ 'haystack', 'reversion', 'guardian', + 'rest_framework', ] WSGI_APPLICATION = 'greenmine.wsgi.application' diff --git a/greenmine/urls.py b/greenmine/urls.py index 52b84fa9..3fa23825 100644 --- a/greenmine/urls.py +++ b/greenmine/urls.py @@ -3,40 +3,11 @@ from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() -from tastypie.api import Api - -from .base.api_actions import Login, Logout -from .scrum.api import * -from .questions.api import * -from .documents.api import * -from .profile.api import * -from .wiki.api import * - -v1_api = Api(api_name='gm') -v1_api.register(ProjectResource()) -v1_api.register(MilestoneResource()) -v1_api.register(UserStoryResource()) -v1_api.register(ChangeResource()) -v1_api.register(ChangeAttachmentResource()) -v1_api.register(TaskResource()) -v1_api.register(QuestionResource()) -v1_api.register(QuestionResponseResource()) -v1_api.register(DocumentResource()) -v1_api.register(ProfileResource()) -v1_api.register(WikiPageResource()) -v1_api.register(WikiPageAttachmentResource()) -v1_api.register(SeverityResource()) -v1_api.register(IssueStatusResource()) -v1_api.register(TaskStatusResource()) -v1_api.register(UserStoryStatusResource()) -v1_api.register(PriorityResource()) -v1_api.register(IssueTypeResource()) -v1_api.register(PointsResource()) - urlpatterns = patterns('', - url(r'^api/gm/actions/login/', Login.as_view(), name="login"), - url(r'^api/gm/actions/logout/', Logout.as_view(), name="logout"), - url(r'^api/', include(v1_api.urls)), + url(r'^api/auth/', include('rest_framework.urls', + namespace='rest_framework')), + url(r'^api/$', 'greenmine.base.views.api_root'), + url(r'^api/scrum/', include('greenmine.scrum.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^grappelli/', include('grappelli.urls')), ) diff --git a/requirements.txt b/requirements.txt index 11bf4eeb..b1706d53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,6 @@ django-grappelli==2.4.4 django-guardian==1.1.0.beta django-reversion==1.7 git+git://github.com/toastdriven/django-haystack.git -django-tastypie==0.9.14 django-picklefield==0.3.0 kombu==2.5.8 mimeparse==0.1.3 @@ -18,3 +17,4 @@ py-bcrypt==0.3 python-dateutil==2.1 pytz==2013b six==1.3.0 +djangorestframework==2.2.5