Commit b5c6bf51 authored by Wietse Kuipers's avatar Wietse Kuipers

Offer same API as old site

Wolktm can't be deprecated because Django doesn't do longpolling
parent f4c3bbfd
...@@ -11,3 +11,4 @@ rcssmin ...@@ -11,3 +11,4 @@ rcssmin
djangorestframework==3.4.4 djangorestframework==3.4.4
django-ical==1.4 django-ical==1.4
django-libsass==0.7 django-libsass==0.7
django-cors-headers
from django.apps import AppConfig
class ThaliappConfig(AppConfig):
name = 'thaliapp'
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-11-03 14:03
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):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Tokens',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.CharField(max_length=64)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-11-03 14:18
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('thaliapp', '0001_initial'),
]
operations = [
migrations.RenameModel(
old_name='Tokens',
new_name='Token',
),
]
from django.db import models
from django.conf import settings
from django.utils.crypto import get_random_string
from django.contrib.auth.models import User
from hashlib import sha256
class Token(models.Model):
"""This class contains an authentication token for an user
An user may have multiple tokens"""
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
token = models.CharField(max_length=64)
@classmethod
def create_token(cls, user):
# Post quantum approved
token = get_random_string(length=64)
hashed_token = sha256(
''.join([user.username, token]).encode()).hexdigest()
t = cls(user=user, token=hashed_token)
t.save()
return token
@classmethod
def authenticate(cls, username, token):
hashed_token = sha256(''.join([username, token]).encode()).hexdigest()
try:
user = User.objects.get(username=username,
token__token=hashed_token)
except User.DoesNotExist:
return None
return user
from django.conf.urls import url
from . import views
app_name = "thaliapp"
urlpatterns = [
url(r'^login', views.login,
name='thaliapp-login'),
url(r'^app', views.app,
name='thaliapp-app'),
]
from django.conf import settings
from django.http import (JsonResponse, HttpResponseBadRequest,
HttpResponseForbidden)
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.contrib.auth import authenticate
from django.contrib.staticfiles.finders import find as find_static_file
from django.core.cache import cache
from thaliapp.models import Token
from hashlib import sha256
import base64
import datetime
def get_photo(user):
if user.member.photo:
photo = ''.join(['data:image/jpeg;base64,',
base64.b64encode(
user.member.photo.file.read()).decode()
])
else:
filename = find_static_file('members/images/default-avatar.jpg')
with open(filename, 'rb') as f:
photo = ''.join(['data:image/jpeg;base64,',
base64.b64encode(f.read()).decode()
])
return photo
@csrf_exempt
@require_POST
def login(request):
if (sha256(request.POST.get('apikey', '').encode('ascii')).hexdigest() !=
settings.THALIAPP_API_KEY):
return HttpResponseForbidden()
user = request.POST.get('username')
password = request.POST.get('password')
if user is None or password is None:
return HttpResponseBadRequest(
'{"status":"error","msg":"Missing username or password"}',
content_type='application/json')
user = authenticate(username=user, password=password)
if user is not None:
token = Token.create_token(user)
photo = get_photo(user)
return JsonResponse({'status': 'ok',
'username': user.username,
'token': token,
'profile_image': photo,
})
return JsonResponse({'status': 'error',
'msg': 'Authentication Failed'},
status_code=403)
@csrf_exempt
@require_POST
def app(request):
username = request.POST.get('username')
token = request.POST.get('token')
if (sha256(request.POST.get('apikey', '').encode('ascii')).hexdigest() !=
settings.WOLKTM_API_KEY):
return HttpResponseForbidden()
if username is None or token is None:
return HttpResponseBadRequest()
user = Token.authenticate(username, token)
if user is None:
return JsonResponse({'status': 'error',
'msg': 'Authentication Failed'},
status_code=403)
today = datetime.date.today()
eightteen_years_ago = today.replace(year=today.year - 18)
over18 = str(user.member.birthday <= eightteen_years_ago)
membership = user.member.current_membership
if membership:
membership_type = membership.type
is_member = 'True'
else:
membership_type = 'Expired'
is_member = 'False'
return JsonResponse({'status': 'ok',
'real_name': user.member.get_full_name(),
'display_name': user.member.display_name(),
'birthday': str(user.member.birthday),
'over18': over18,
'membership_type': membership_type,
'is_thalia_member': is_member,
'profile_image': get_photo(user),
})
@csrf_exempt
@require_POST
def scan(request):
"""Not used until wolktm is deprecated"""
username = request.POST.get('username')
token = request.POST.get('token')
qrtoken = request.POST.get('qrToken')
if username is None or token is None or qrtoken is None:
return HttpResponseBadRequest()
user = Token.authenticate(username, token)
if user is None:
return JsonResponse({'status': 'error',
'msg': 'Authentication Failed'},
status_code=403)
cache.set(''.join([qrtoken]), user, 300)
return JsonResponse({'status': 'ok'})
...@@ -51,6 +51,7 @@ INSTALLED_APPS = [ ...@@ -51,6 +51,7 @@ INSTALLED_APPS = [
'django_template_check', # This is only necessary in development 'django_template_check', # This is only necessary in development
'rest_framework', 'rest_framework',
'compressor', 'compressor',
'corsheaders',
# Our apps # Our apps
'thaliawebsite', # include for admin settings 'thaliawebsite', # include for admin settings
'members', 'members',
...@@ -66,11 +67,13 @@ INSTALLED_APPS = [ ...@@ -66,11 +67,13 @@ INSTALLED_APPS = [
'pizzas', 'pizzas',
'newsletters', 'newsletters',
'education', 'education',
'thaliapp',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
...@@ -207,3 +210,13 @@ PHOTO_UPLOAD_SIZE = 1920, 1080 ...@@ -207,3 +210,13 @@ PHOTO_UPLOAD_SIZE = 1920, 1080
# API key for wiki # API key for wiki
WIKI_API_KEY = 'debug' WIKI_API_KEY = 'debug'
# API key for thaliapp related stuff
# SHA256 hash so it does not need replacement in production
THALIAPP_API_KEY = ('5b2bff55b74f74678dd578f8f669e959'
'09f356aa05548ecdf418e678af334844')
WOLKTM_API_KEY = 'vulditin'
# CORS config
CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/.*$'
CORS_ALLOW_METHODS = ('GET', 'POST')
...@@ -83,6 +83,7 @@ urlpatterns = [ ...@@ -83,6 +83,7 @@ urlpatterns = [
url(r'^', include('events.api.urls')), url(r'^', include('events.api.urls')),
url(r'^', include('members.api.urls')), url(r'^', include('members.api.urls')),
url(r'^', include('partners.api.urls')), url(r'^', include('partners.api.urls')),
url(r'^', include('thaliapp.urls')),
url(r'wikilogin', views.wiki_login), url(r'wikilogin', views.wiki_login),
])), ])),
url(r'^education/', include('education.urls', namespace='education')), url(r'^education/', include('education.urls', namespace='education')),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment