From 6b87b2b7014a0441f5f696a35127f12a89e48d2e Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 28 Feb 2019 23:46:46 +0100 Subject: [PATCH 1/1] Move API models to api app. --- src/api/{piston => }/admin.py | 0 .../0005_consumer_nonce_resource_token.py | 57 +++++++++++++++++++ src/api/models.py | 50 ++++++++++++++++ .../migrations/0002_auto_20190228_2338.py | 52 +++++++++++++++++ src/api/piston/models.py | 56 ------------------ src/api/request_validator.py | 4 +- src/api/tests/tests.py | 2 +- src/api/views.py | 2 +- 8 files changed, 163 insertions(+), 60 deletions(-) rename src/api/{piston => }/admin.py (100%) create mode 100644 src/api/migrations/0005_consumer_nonce_resource_token.py create mode 100644 src/api/piston/migrations/0002_auto_20190228_2338.py diff --git a/src/api/piston/admin.py b/src/api/admin.py similarity index 100% rename from src/api/piston/admin.py rename to src/api/admin.py diff --git a/src/api/migrations/0005_consumer_nonce_resource_token.py b/src/api/migrations/0005_consumer_nonce_resource_token.py new file mode 100644 index 000000000..95873a7e3 --- /dev/null +++ b/src/api/migrations/0005_consumer_nonce_resource_token.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-02-28 22:38 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('api', '0004_bookuserdata_last_changed'), + ('piston', '0002_auto_20190228_2338'), + ] + + state_operations = [ + migrations.CreateModel( + name='Consumer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField()), + ('key', models.CharField(max_length=18)), + ('secret', models.CharField(max_length=32)), + ('status', models.CharField(choices=[(b'pending', b'Pending approval'), (b'accepted', b'Accepted'), (b'canceled', b'Canceled')], default=b'pending', max_length=16)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='consumers', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Nonce', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('token_key', models.CharField(max_length=18)), + ('consumer_key', models.CharField(max_length=18)), + ('key', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='Token', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.CharField(max_length=18)), + ('secret', models.CharField(max_length=32)), + ('token_type', models.IntegerField(choices=[(1, 'Request'), (2, 'Access')])), + ('timestamp', models.IntegerField()), + ('is_approved', models.BooleanField(default=False)), + ('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Consumer')), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL)), + ], + ), + ] + + operations = [ + migrations.SeparateDatabaseAndState(state_operations=state_operations), + ] diff --git a/src/api/models.py b/src/api/models.py index d2716b922..71dedb56c 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -2,6 +2,7 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.db import models @@ -57,3 +58,52 @@ class BookUserData(models.Model): instance.complete = state == 'complete' instance.save() return instance +from django.conf import settings + + +KEY_SIZE = 18 +SECRET_SIZE = 32 + +CONSUMER_STATES = ( + ('pending', 'Pending approval'), + ('accepted', 'Accepted'), + ('canceled', 'Canceled'), +) + + +class Nonce(models.Model): + token_key = models.CharField(max_length=KEY_SIZE) + consumer_key = models.CharField(max_length=KEY_SIZE) + key = models.CharField(max_length=255) + + def __unicode__(self): + return u"Nonce %s for %s" % (self.key, self.consumer_key) + + +class Consumer(models.Model): + name = models.CharField(max_length=255) + description = models.TextField() + key = models.CharField(max_length=KEY_SIZE) + secret = models.CharField(max_length=SECRET_SIZE) + status = models.CharField(max_length=16, choices=CONSUMER_STATES, default='pending') + user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='consumers') + + def __unicode__(self): + return u"Consumer %s with key %s" % (self.name, self.key) + + +class Token(models.Model): + REQUEST = 1 + ACCESS = 2 + TOKEN_TYPES = ((REQUEST, u'Request'), (ACCESS, u'Access')) + + key = models.CharField(max_length=KEY_SIZE) + secret = models.CharField(max_length=SECRET_SIZE) + token_type = models.IntegerField(choices=TOKEN_TYPES) + timestamp = models.IntegerField() + is_approved = models.BooleanField(default=False) + user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='tokens') + consumer = models.ForeignKey(Consumer) + + def __unicode__(self): + return u"%s Token %s for %s" % (self.get_token_type_display(), self.key, self.consumer) diff --git a/src/api/piston/migrations/0002_auto_20190228_2338.py b/src/api/piston/migrations/0002_auto_20190228_2338.py new file mode 100644 index 000000000..4fa2b9057 --- /dev/null +++ b/src/api/piston/migrations/0002_auto_20190228_2338.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-02-28 22:38 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('piston', '0001_initial'), + ] + + database_operations = [ + migrations.AlterModelTable('Nonce', 'api_nonce'), + migrations.AlterModelTable('Consumer', 'api_consumer'), + migrations.AlterModelTable('Token', 'api_token'), + ] + + state_operations = [ + migrations.RemoveField( + model_name='consumer', + name='user', + ), + migrations.DeleteModel( + name='Nonce', + ), + migrations.RemoveField( + model_name='token', + name='consumer', + ), + migrations.RemoveField( + model_name='token', + name='user', + ), + migrations.DeleteModel( + name='Consumer', + ), + migrations.DeleteModel( + name='Token', + ), + ] + + operations = [ + migrations.SeparateDatabaseAndState( + database_operations=database_operations, + state_operations=state_operations + ), + migrations.DeleteModel( + name='Resource', + ), + ] diff --git a/src/api/piston/models.py b/src/api/piston/models.py index 7bb106c81..e69de29bb 100644 --- a/src/api/piston/models.py +++ b/src/api/piston/models.py @@ -1,56 +0,0 @@ -from django.conf import settings -from django.db import models - - -KEY_SIZE = 18 -SECRET_SIZE = 32 - -CONSUMER_STATES = ( - ('pending', 'Pending approval'), - ('accepted', 'Accepted'), - ('canceled', 'Canceled'), -) - - -class Nonce(models.Model): - token_key = models.CharField(max_length=KEY_SIZE) - consumer_key = models.CharField(max_length=KEY_SIZE) - key = models.CharField(max_length=255) - - def __unicode__(self): - return u"Nonce %s for %s" % (self.key, self.consumer_key) - - -class Resource(models.Model): - name = models.CharField(max_length=255) - url = models.TextField(max_length=2047) - is_readonly = models.BooleanField(default=True) - - -class Consumer(models.Model): - name = models.CharField(max_length=255) - description = models.TextField() - key = models.CharField(max_length=KEY_SIZE) - secret = models.CharField(max_length=SECRET_SIZE) - status = models.CharField(max_length=16, choices=CONSUMER_STATES, default='pending') - user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='consumers') - - def __unicode__(self): - return u"Consumer %s with key %s" % (self.name, self.key) - - -class Token(models.Model): - REQUEST = 1 - ACCESS = 2 - TOKEN_TYPES = ((REQUEST, u'Request'), (ACCESS, u'Access')) - - key = models.CharField(max_length=KEY_SIZE) - secret = models.CharField(max_length=SECRET_SIZE) - token_type = models.IntegerField(choices=TOKEN_TYPES) - timestamp = models.IntegerField() - is_approved = models.BooleanField(default=False) - user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='tokens') - consumer = models.ForeignKey(Consumer) - - def __unicode__(self): - return u"%s Token %s for %s" % (self.get_token_type_display(), self.key, self.consumer) diff --git a/src/api/request_validator.py b/src/api/request_validator.py index 55bd6fbdb..2c16691f8 100644 --- a/src/api/request_validator.py +++ b/src/api/request_validator.py @@ -4,7 +4,7 @@ # import time from oauthlib.oauth1 import RequestValidator -from api.piston.models import Consumer, Nonce, Token +from api.models import Consumer, Nonce, Token class PistonRequestValidator(RequestValidator): @@ -20,7 +20,7 @@ class PistonRequestValidator(RequestValidator): # iOS app generates 8-char nonces. nonce_length = 8, 250 - # Because piston.models.Token.key is char(18). + # Because Token.key is char(18). request_token_length = 18, 32 access_token_length = 18, 32 # TODO: oauthlib request-access switch. diff --git a/src/api/tests/tests.py b/src/api/tests/tests.py index 8dd29a5b6..b3cc54fc9 100644 --- a/src/api/tests/tests.py +++ b/src/api/tests/tests.py @@ -17,7 +17,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase from django.test.utils import override_settings from mock import patch -from api.piston.models import Consumer, Token +from api.models import Consumer, Token from catalogue.models import Book, Tag from picture.forms import PictureImportForm diff --git a/src/api/views.py b/src/api/views.py index f28a4e4e1..741e45420 100644 --- a/src/api/views.py +++ b/src/api/views.py @@ -6,7 +6,7 @@ from django.http import Http404 from django.views.generic.base import View from oauthlib.common import urlencode from oauthlib.oauth1 import RequestTokenEndpoint, AccessTokenEndpoint -from api.piston.models import KEY_SIZE, SECRET_SIZE +from api.models import KEY_SIZE, SECRET_SIZE from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -- 2.20.1