From 9bbfea8971ad33970e2c60dd6078ec4154cf772a Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 7 Jan 2015 02:12:07 +0100 Subject: [PATCH] This should allmost work --- .gitignore | 2 + README => README.md | 0 {pfrsite => dpdapi}/__init__.py | 0 dpdapi/admin.py | 19 ++++++ dpdapi/migrations/0001_initial.py | 62 +++++++++++++++++++ .../migrations}/__init__.py | 0 dpdapi/models.py | 40 ++++++++++++ dpdapi/serializers.py | 24 +++++++ {postfixrest => dpdapi}/tests.py | 0 dpdapi/urls.py | 10 +++ dpdapi/views.py | 57 +++++++++++++++++ .../migrations => dpdapisite}/__init__.py | 0 {pfrsite => dpdapisite}/settings.py | 25 ++++++-- dpdapisite/urls.py | 11 ++++ {pfrsite => dpdapisite}/wsgi.py | 2 +- manage.py | 2 +- pfrsite/urls.py | 10 --- postfixrest/admin.py | 3 - postfixrest/models.py | 9 --- postfixrest/views.py | 3 - requirements.txt | 5 +- 21 files changed, 250 insertions(+), 34 deletions(-) rename README => README.md (100%) rename {pfrsite => dpdapi}/__init__.py (100%) create mode 100644 dpdapi/admin.py create mode 100644 dpdapi/migrations/0001_initial.py rename {postfixrest => dpdapi/migrations}/__init__.py (100%) create mode 100644 dpdapi/models.py create mode 100644 dpdapi/serializers.py rename {postfixrest => dpdapi}/tests.py (100%) create mode 100644 dpdapi/urls.py create mode 100644 dpdapi/views.py rename {postfixrest/migrations => dpdapisite}/__init__.py (100%) rename {pfrsite => dpdapisite}/settings.py (81%) create mode 100644 dpdapisite/urls.py rename {pfrsite => dpdapisite}/wsgi.py (81%) delete mode 100644 pfrsite/urls.py delete mode 100644 postfixrest/admin.py delete mode 100644 postfixrest/models.py delete mode 100644 postfixrest/views.py diff --git a/.gitignore b/.gitignore index bc56ebf..420f626 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.pyc .idea venv +local_settings.py +db.sqlite3 diff --git a/README b/README.md similarity index 100% rename from README rename to README.md diff --git a/pfrsite/__init__.py b/dpdapi/__init__.py similarity index 100% rename from pfrsite/__init__.py rename to dpdapi/__init__.py diff --git a/dpdapi/admin.py b/dpdapi/admin.py new file mode 100644 index 0000000..34b3a85 --- /dev/null +++ b/dpdapi/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin + +from dpdapi.models import Alias, Domain, User + + +@admin.register(Alias) +class AliasAdmin(admin.ModelAdmin): + list_display = ['source', 'destination', 'active', 'domain'] + list_filter = ['domain'] + + +@admin.register(Domain) +class DomainAdmin(admin.ModelAdmin): + pass + + +@admin.register(User) +class UserAdmin(admin.ModelAdmin): + pass \ No newline at end of file diff --git a/dpdapi/migrations/0001_initial.py b/dpdapi/migrations/0001_initial.py new file mode 100644 index 0000000..e533c37 --- /dev/null +++ b/dpdapi/migrations/0001_initial.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Alias', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('source', models.EmailField(max_length=75)), + ('destination', models.EmailField(max_length=75)), + ('active', models.BooleanField(default=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Domain', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=1000)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('email', models.EmailField(max_length=75)), + ('password', models.CharField(max_length=109)), + ('domain', models.ForeignKey(to='dpdapi.Domain')), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='alias', + name='domain', + field=models.ForeignKey(to='dpdapi.Domain'), + preserve_default=True, + ), + ] diff --git a/postfixrest/__init__.py b/dpdapi/migrations/__init__.py similarity index 100% rename from postfixrest/__init__.py rename to dpdapi/migrations/__init__.py diff --git a/dpdapi/models.py b/dpdapi/models.py new file mode 100644 index 0000000..a53b521 --- /dev/null +++ b/dpdapi/models.py @@ -0,0 +1,40 @@ +from __future__ import unicode_literals +from django.db import models + + +class BaseModel(models.Model): + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True + + +class Alias(BaseModel): + source = models.EmailField() + destination = models.EmailField() + domain = models.ForeignKey('dpdapi.Domain') + active = models.BooleanField(default=True) + + def __unicode__(self): + return "{}={}".format(self.source, self.destination) + + class Meta: + verbose_name_plural = 'aliases' + + +class Domain(BaseModel): + name = models.CharField(max_length=1000) + + def __unicode__(self): + return self.name + + +class User(BaseModel): + email = models.EmailField() + password = models.CharField(max_length=109) + domain = models.ForeignKey('dpdapi.Domain') + + def __unicode__(self): + return self.email + diff --git a/dpdapi/serializers.py b/dpdapi/serializers.py new file mode 100644 index 0000000..f42d661 --- /dev/null +++ b/dpdapi/serializers.py @@ -0,0 +1,24 @@ +from rest_framework import serializers + +from .models import Alias, Domain, User + + +class AliasSerializer(serializers.ModelSerializer): + class Meta: + model = Alias + + +class AliasIdSerializer(serializers.ModelSerializer): + class Meta: + model = Alias + fields = ['id'] + + +class DomainSerializer(serializers.ModelSerializer): + class Meta: + model = Domain + + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User \ No newline at end of file diff --git a/postfixrest/tests.py b/dpdapi/tests.py similarity index 100% rename from postfixrest/tests.py rename to dpdapi/tests.py diff --git a/dpdapi/urls.py b/dpdapi/urls.py new file mode 100644 index 0000000..f70d09e --- /dev/null +++ b/dpdapi/urls.py @@ -0,0 +1,10 @@ +from rest_framework.routers import DefaultRouter + +from .views import AliasViewSet, DomainViewSet, UserViewSet + + +router = DefaultRouter() +router.register(r'aliases', AliasViewSet) +router.register(r'domains', DomainViewSet) +router.register(r'users', UserViewSet) +urlpatterns = router.urls \ No newline at end of file diff --git a/dpdapi/views.py b/dpdapi/views.py new file mode 100644 index 0000000..19ab147 --- /dev/null +++ b/dpdapi/views.py @@ -0,0 +1,57 @@ +from __future__ import unicode_literals +from rest_framework.decorators import list_route +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework import status, filters, viewsets + +from .models import Alias, Domain, User +from .serializers import AliasSerializer, AliasIdSerializer, DomainSerializer, UserSerializer + + +class AliasViewSet(viewsets.ModelViewSet): + """ Aliases """ + queryset = Alias.objects.all() + serializer_class = AliasSerializer + permission_classes = [IsAuthenticated] + filter_backends = (filters.DjangoFilterBackend,) + filter_fields = ('domain', 'domain__name') + + @list_route(methods=['post']) + def create_bulk(self, request): + serializer = AliasSerializer(data=request.data, many=True) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + @list_route(methods=['delete']) + def delete_bulk(self, request): + # TODO how to lookup instances and delete them by id? + serializer = AliasIdSerializer(data=request.data, many=True) + if not serializer.is_valid(): + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + ids = map(lambda x: x['id'], serializer.initial_data) # FIXME this is not how to do it + aliases = Alias.objects.filter(id__in=ids) + diff = set(ids).difference(set(aliases.values_list('id', flat=True))) + aliases.delete() + + if diff: + result = "ID's '{}' could not be found and were not deleted.".format(", ".join(map(str, diff))) + return Response({"result": result}, status=status.HTTP_200_OK) + + return Response(status=status.HTTP_204_NO_CONTENT) + + +class DomainViewSet(viewsets.ModelViewSet): + """ Domains """ + queryset = Domain.objects.all() + serializer_class = DomainSerializer + permission_classes = [IsAuthenticated] + + +class UserViewSet(viewsets.ModelViewSet): + """ Users """ + queryset = User.objects.all() + serializer_class = UserSerializer + permission_classes = [IsAuthenticated] diff --git a/postfixrest/migrations/__init__.py b/dpdapisite/__init__.py similarity index 100% rename from postfixrest/migrations/__init__.py rename to dpdapisite/__init__.py diff --git a/pfrsite/settings.py b/dpdapisite/settings.py similarity index 81% rename from pfrsite/settings.py rename to dpdapisite/settings.py index 44c0001..925545b 100644 --- a/pfrsite/settings.py +++ b/dpdapisite/settings.py @@ -1,6 +1,4 @@ """ -Django settings for pfrsite project. - For more information on this file, see https://docs.djangoproject.com/en/1.7/topics/settings/ @@ -38,6 +36,11 @@ INSTALLED_APPS = ( 'django.contrib.staticfiles', ) +INSTALLED_APPS += ( + 'rest_framework', + 'dpdapi', +) + MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -48,9 +51,9 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) -ROOT_URLCONF = 'pfrsite.urls' +ROOT_URLCONF = 'dpdapisite.urls' -WSGI_APPLICATION = 'pfrsite.wsgi.application' +WSGI_APPLICATION = 'dpdapisite.wsgi.application' # Database @@ -68,7 +71,7 @@ DATABASES = { LANGUAGE_CODE = 'en-us' -TIME_ZONE = 'UTC' +TIME_ZONE = 'Europe/Oslo' USE_I18N = True @@ -81,3 +84,15 @@ USE_TZ = True # https://docs.djangoproject.com/en/1.7/howto/static-files/ STATIC_URL = '/static/' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.BasicAuthentication', + 'rest_framework.authentication.SessionAuthentication', + ) +} + +try: + from local_settings import * +except ImportError: + pass \ No newline at end of file diff --git a/dpdapisite/urls.py b/dpdapisite/urls.py new file mode 100644 index 0000000..386e07f --- /dev/null +++ b/dpdapisite/urls.py @@ -0,0 +1,11 @@ +from django.conf.urls import patterns, include, url +from django.contrib import admin +from django.views.generic import RedirectView + +urlpatterns = patterns( + '', + url(r'^api/', include('dpdapi.urls')), + url(r'^$', RedirectView.as_view(pattern_name='api-root')), + url(r'^admin/', include(admin.site.urls)), + url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) +) diff --git a/pfrsite/wsgi.py b/dpdapisite/wsgi.py similarity index 81% rename from pfrsite/wsgi.py rename to dpdapisite/wsgi.py index 29e0a42..34db734 100644 --- a/pfrsite/wsgi.py +++ b/dpdapisite/wsgi.py @@ -8,7 +8,7 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pfrsite.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dpdapisite.settings") from django.core.wsgi import get_wsgi_application application = get_wsgi_application() diff --git a/manage.py b/manage.py index d2424f6..8f5160c 100755 --- a/manage.py +++ b/manage.py @@ -3,7 +3,7 @@ import os import sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pfrsite.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dpdapisite.settings") from django.core.management import execute_from_command_line diff --git a/pfrsite/urls.py b/pfrsite/urls.py deleted file mode 100644 index dec5c09..0000000 --- a/pfrsite/urls.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.conf.urls import patterns, include, url -from django.contrib import admin - -urlpatterns = patterns('', - # Examples: - # url(r'^$', 'pfrsite.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), - - url(r'^admin/', include(admin.site.urls)), -) diff --git a/postfixrest/admin.py b/postfixrest/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/postfixrest/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/postfixrest/models.py b/postfixrest/models.py deleted file mode 100644 index 0f0cd3d..0000000 --- a/postfixrest/models.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.db import models - - -#TODO: Domain, User - -class Alias(models.Model): - active = models.BooleanField(default=True) - src = models.EmailField() - # TODO: dst EmailListField \ No newline at end of file diff --git a/postfixrest/views.py b/postfixrest/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/postfixrest/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/requirements.txt b/requirements.txt index 7da5c48..105d518 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Django>=1.7,<1.8 -django-extensions==1.4.0 -djangorestframework==2.4.3 +django-extensions==1.4.9 +django-filter==0.9.1 +djangorestframework>=3.0,<3.1