Initial rfid models, to think about any thoughts ?

remove mapping model on base on @scollins suggestion

Updated models, enabled it in the admin backup to get an idea of the structure.
will need to rebuild, updating restframework

current state of experiment into rfid api

Change docs url

started looking into web tokens

Refactor models

More experimenting

Custom view now works, needs tiding up and data to test
This commit is contained in:
Oliver Marks 2017-04-09 09:57:23 +01:00 committed by Oly
parent 28e0cd8f94
commit 69af967ae6
15 changed files with 310 additions and 4 deletions

View File

@ -5,7 +5,6 @@
Repository for the maidstone hackspace website, feel free to fork this site for your own Hackspace. Repository for the maidstone hackspace website, feel free to fork this site for your own Hackspace.
** Requirements ** Requirements
Before getting started make sure you have git, docker and docker-compose installed on your machine. Before getting started make sure you have git, docker and docker-compose installed on your machine.
The simplest way to setup this site is to use docker-compose so please install that from this site The simplest way to setup this site is to use docker-compose so please install that from this site
@ -47,7 +46,7 @@ docker-compose -f dev.yml run --rm django python manage.py makemigrations
docker-compose -f dev.yml run --rm django python manage.py migrate docker-compose -f dev.yml run --rm django python manage.py migrate
#+END_SRC #+END_SRC
*** Create the admin user. *** Create the admin user.
Once created you can login at http://127.0.0.1:8180/admin Once created you can login at http://127.0.0.1:8180/trustee
#+BEGIN_SRC sh #+BEGIN_SRC sh
docker-compose -f dev.yml run --rm django python manage.py createsuperuser docker-compose -f dev.yml run --rm django python manage.py createsuperuser
#+END_SRC #+END_SRC

View File

@ -80,6 +80,7 @@ THIRD_PARTY_APPS = (
'whitenoise.runserver_nostatic', 'whitenoise.runserver_nostatic',
'stdimage', 'stdimage',
'rest_framework', 'rest_framework',
'django_filters',
'draceditor', 'draceditor',
'haystack', 'haystack',
'djconfig', 'djconfig',
@ -138,6 +139,7 @@ LOCAL_APPS = (
'mhackspace.blog', 'mhackspace.blog',
'mhackspace.core', 'mhackspace.core',
'mhackspace.requests', 'mhackspace.requests',
'mhackspace.rfid',
) )
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
@ -446,10 +448,12 @@ REST_FRAMEWORK = {
'rest_framework.filters.OrderingFilter' 'rest_framework.filters.OrderingFilter'
), ),
'DEFAULT_PERMISSION_CLASSES': ( 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly', # 'rest_framework.permissions.IsAuthenticated',
# 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
), ),
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.TokenAuthentication',
), ),

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from django.conf.urls.static import static from django.conf.urls.static import static
@ -9,6 +10,7 @@ from django.views import defaults as default_views
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.contrib.sitemaps.views import sitemap from django.contrib.sitemaps.views import sitemap
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from rest_framework.documentation import include_docs_urls
from mhackspace.contact.views import contact from mhackspace.contact.views import contact
from mhackspace.members.views import MemberListView from mhackspace.members.views import MemberListView
@ -20,21 +22,28 @@ from mhackspace.blog.views import PostViewSet, CategoryViewSet, BlogPost, PostLi
from mhackspace.blog.sitemaps import PostSitemap, CategorySitemap from mhackspace.blog.sitemaps import PostSitemap, CategorySitemap
from mhackspace.feeds.views import FeedViewSet, ArticleViewSet from mhackspace.feeds.views import FeedViewSet, ArticleViewSet
from mhackspace.requests.views import RequestsForm, RequestsList from mhackspace.requests.views import RequestsForm, RequestsList
from mhackspace.rfid.views import DeviceViewSet, AuthUserWithDeviceViewSet
from wiki.urls import get_pattern as get_wiki_pattern from wiki.urls import get_pattern as get_wiki_pattern
from django_nyt.urls import get_pattern as get_nyt_pattern from django_nyt.urls import get_pattern as get_nyt_pattern
from rest_framework_jwt.views import obtain_jwt_token
router = DefaultRouter() router = DefaultRouter()
router.register(r'posts', PostViewSet) router.register(r'posts', PostViewSet)
router.register(r'categories', CategoryViewSet) router.register(r'categories', CategoryViewSet)
router.register(r'feeds', FeedViewSet) router.register(r'feeds', FeedViewSet)
router.register(r'articles', ArticleViewSet) router.register(r'articles', ArticleViewSet)
router.register(r'rfid', DeviceViewSet)
router.register(r'rfidAuth', AuthUserWithDeviceViewSet, base_name='device')
sitemaps = { sitemaps = {
'posts': PostSitemap, 'posts': PostSitemap,
'category': CategorySitemap, 'category': CategorySitemap,
} }
urlpatterns = [ urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name='home'), url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name='home'),
url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name='about'), url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name='about'),
@ -68,6 +77,9 @@ urlpatterns = [
# Django Admin, use {% url 'admin:index' %} # Django Admin, use {% url 'admin:index' %}
url(r'{}'.format(settings.ADMIN_URL), admin.site.urls), url(r'{}'.format(settings.ADMIN_URL), admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^api/docs/', include_docs_urls(title='Hackspace API')),
# User management # User management
url(r'^users/', include('mhackspace.users.urls', namespace='users')), url(r'^users/', include('mhackspace.users.urls', namespace='users')),
url(r'^accounts/', include('allauth.urls')), url(r'^accounts/', include('allauth.urls')),

View File

14
mhackspace/rfid/admin.py Normal file
View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.contrib.admin import ModelAdmin
from mhackspace.rfid.models import Device, Rfid
@admin.register(Device)
class DeviceAdmin(ModelAdmin):
list_display = ('name',)
@admin.register(Rfid)
class RfidAdmin(ModelAdmin):
list_display = ('code',)

View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-04-14 21:15
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Device',
fields=[
('identifier', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.CharField(max_length=255, verbose_name='Device name')),
('description', models.CharField(blank=True, max_length=255, verbose_name='Short description of what the device does')),
('added_date', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
],
),
migrations.CreateModel(
name='DeviceAuth',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('device', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='device', to='rfid.Device')),
('user', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_auth', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Rfid',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.PositiveIntegerField()),
('description', models.CharField(blank=True, max_length=255, verbose_name='Short rfid description')),
('user', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rfid_user', to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-04-20 07:30
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),
('rfid', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='deviceauth',
name='device',
),
migrations.RemoveField(
model_name='deviceauth',
name='user',
),
migrations.AddField(
model_name='device',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='rfid',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='DeviceAuth',
),
]

View File

60
mhackspace/rfid/models.py Normal file
View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import
import uuid
from django.utils import timezone
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
# just brainstorming so we can start playing with this,
# be nice to make this a 3rd party django installable app ?
# users rfid card to user mapping, user can have more than one card
class Rfid(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True, blank=True,
# related_name='rfid_user'
)
code = models.PositiveIntegerField()
description = models.CharField(_('Short rfid description'), blank=True, max_length=255)
def __str__(self):
return self.description
# description of a device like door, print, laser cutter
class Device(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True, blank=True,
# related_name='rfid_user'
)
# user = models.ManyToMany(settings.AUTH_USER_MODEL)
identifier = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(_('Device name'), max_length=255)
description = models.CharField(_('Short description of what the device does'), blank=True, max_length=255)
added_date = models.DateTimeField(default=timezone.now, editable=False)
def __str__(self):
return self.name
# many to many, lookup user from rfid model then get there user_id and the device to check if auth allowed
# class DeviceAuth(models.Model):
# user = models.ForeignKey(
# settings.AUTH_USER_MODEL,
# null=True, blank=True,
# default=None,
# related_name='user_auth'
# )
# device = models.ForeignKey(
# Device,
# null=True, blank=True,
# default=None,
# related_name='device'
# )

View File

@ -0,0 +1,32 @@
from rest_framework import serializers
from mhackspace.rfid.models import Device
class Task(object):
def __init__(self, **kwargs):
for field in ('id', 'name', 'owner', 'status'):
setattr(self, field, kwargs.get(field, None))
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = ('name', )
class AuthSerializer(serializers.Serializer):
name = serializers.CharField(max_length=255)
rfid = serializers.CharField(max_length=255)
device_id = serializers.CharField(max_length=255)
# def create(self, validated_data):
# return Task(id=None, **validated_data)
# def update(self, instance, validated_data):
# for field, value in validated_data.items():
# setattr(instance, field, value)
# return instance
# class Meta:
# fields = ('name', )

View File

View File

@ -0,0 +1,58 @@
import sys
import requests
from io import StringIO
from django.core.management import call_command
from test_plus.test import TestCase
from rest_framework.test import APIRequestFactory
from rest_framework.test import RequestsClient
from mhackspace.rfid.models import Device
from mhackspace.user.models import User
# http://www.django-rest-framework.org/api-guide/testing/
class MigrationTestCase(TestCase):
def testRollback(self):
out = StringIO()
sys.stout = out
call_command('migrate', 'rfid', 'zero', stdout=out)
call_command('migrate', 'rfid', stdout=out)
self.assertIn("... OK\n", out.getvalue())
class ApiTests(TestCase):
def setUp(self):
Device(name='device01').save()
User(name='User01').save()
Rfid(code=1, user=1).save()
def testAuth(self):
factory = APIRequestFactory()
request = factory.get('/rfid/')
def testSamsMadness(self):
client = RequestsClient()
response = client.post(
'http://127.0.0.1:8180/api/v1/rfidAuth/?format=json',
data={'rfid':'1', 'device': '1'})
print(response)
assert response.status_code == 200
self.assertEquals(response.json().get('results'), [{'name': 'device01'}])
def testAuthUserWithDevice(self):
client = RequestsClient()
response = client.get('http://127.0.0.1:8180/api/v1/rfid/?format=json')
assert response.status_code == 200
self.assertEquals(response.json().get('results'), [{'name': 'device01'}])
def testFetchDeviceList(self):
client = RequestsClient()
response = client.get('http://127.0.0.1:8180/api/v1/rfid/?format=json')
assert response.status_code == 200
self.assertEquals(response.json().get('results'), [{'name': 'device01'}])

32
mhackspace/rfid/views.py Normal file
View File

@ -0,0 +1,32 @@
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import viewsets
from mhackspace.rfid.models import Device, Rfid
from mhackspace.rfid.serializers import DeviceSerializer, AuthSerializer
from django.shortcuts import get_list_or_404, get_object_or_404
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
#https://medium.com/django-rest-framework/django-rest-framework-viewset-when-you-don-t-have-a-model-335a0490ba6f
class AuthUserWithDeviceViewSet(viewsets.ViewSet):
# http_method_names = ['get', 'post', 'head']
serializer_class = AuthSerializer
def list(self, request):
serializer = AuthSerializer(instance={'name': '1','rfid': '1', 'device_id': '1'})
return Response(serializer.data)
def post(self, request, format=None):
rfid = Rfid.objects.get(code=request.GET.get('rfid_id'))
print(rfid.user.device__set(device=request.GET.get('rfid_id')))
# = get_object_or_404(Disease, pk=disease_id)
# Device(rfid, device)
serializer = AuthSerializer(instance={'name': '1', 'rfid': '1', 'device_id': '1'})
return Response(serializer.data)

View File

@ -21,3 +21,9 @@
[hidden][style="display: block;"] { [hidden][style="display: block;"] {
display: block !important; display: block !important;
} }
.imgfit {
width:100%;
height: auto;
overflow: hidden;
}

View File

@ -61,7 +61,10 @@ git+https://github.com/olymk2/scaffold.git
git+git://github.com/django-wiki/django-wiki.git git+git://github.com/django-wiki/django-wiki.git
djangorestframework==3.6.3 djangorestframework==3.6.3
djangorestframework-jwt
django-filter==1.0.2 django-filter==1.0.2
coreapi
# api libraries end
draceditor==1.1.8 draceditor==1.1.8
# django-spirit # django-spirit