From 28fabd437ce0ca637b8fdf2867942396df469fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastiaan=20Versteeg?= Date: Thu, 9 Feb 2017 13:49:40 +0100 Subject: [PATCH] Add route for login and permissions, return JSON on unauthorized API requests --- marietje/api/urls.py | 2 ++ marietje/api/views.py | 82 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/marietje/api/urls.py b/marietje/api/urls.py index f328f81..2e58268 100644 --- a/marietje/api/urls.py +++ b/marietje/api/urls.py @@ -5,6 +5,8 @@ from . import views app_name = 'api' urlpatterns = [ + url(r'^login', views.login_user), + url(r'^permissions', views.permissions), url(r'^songs', views.songs), url(r'^managesongs', views.managesongs), url(r'^queue', views.queue), diff --git a/marietje/api/views.py b/marietje/api/views.py index 73e16eb..a1ba7e9 100644 --- a/marietje/api/views.py +++ b/marietje/api/views.py @@ -1,20 +1,72 @@ import time -from mutagen import File +from functools import wraps -from django.contrib.auth.decorators import login_required +import django.middleware.csrf as csrf +from django.contrib.auth import authenticate, login from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.db.models import Q from django.http import JsonResponse, HttpResponseForbidden from django.shortcuts import get_object_or_404 from django.views.decorators.http import require_http_methods +from mutagen import File from marietje.utils import song_to_dict, playlist_song_to_dict, send_to_bertha - +from queues.models import PlaylistSong, QueueCommand from songs.models import Song -from queues.models import PlaylistSong, Queue, QueueCommand -@login_required +def api_auth_required(view_func): + @wraps(view_func) + def _wrapped_view(request, *args, **kwargs): + if request.user.is_authenticated and request.user.is_active: + return view_func(request, *args, **kwargs) + response = JsonResponse({ + 'error': 'User not authenticated or activated.' + }) + response.status_code = 401 + return response + + return _wrapped_view + + +def login_user(request): + data = {'error': 'Method not allowed'} + status = 405 + if request.method == "POST": + username = request.POST.get('username', '').strip() + password = request.POST.get('password', '').strip() + + data = {'error': 'Please enter a correct username and password. ' + 'Note that both fields may be case-sensitive.'} + status = 401 + + if username and password: + user = authenticate(username=username, password=password) + if user is not None: + if user.is_active: + login(request, user) + data = {} + status = 200 + else: + data = {'error': 'User is not active'} + status = 401 + else: + csrf.get_token(request) + response = JsonResponse(data) + response.status_code = status + return response + + +@api_auth_required +def permissions(request): + return JsonResponse({ + 'can_move': request.user.has_perm('queues.can_move'), + 'can_skip': request.user.has_perm('queues.can_skip'), + 'can_cancel': request.user.has_perm('queues.can_cancel') + }) + + +@api_auth_required def songs(request): try: pagesize = int(request.POST.get('pagesize')) @@ -57,7 +109,7 @@ def songs(request): }) -@login_required +@api_auth_required def managesongs(request): try: pagesize = int(request.POST.get('pagesize')) @@ -99,7 +151,7 @@ def managesongs(request): }) -@login_required +@api_auth_required def queue(request): queue = request.user.queue return JsonResponse({ @@ -110,7 +162,7 @@ def queue(request): }) -@login_required +@api_auth_required def skip(request): playlist_song = request.user.queue.current_song() if playlist_song.user != request.user and not request.user.has_perm('queues.can_skip'): @@ -123,7 +175,7 @@ def skip(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def move_up(request): if not request.user.has_perm('queues.can_move'): return HttpResponseForbidden() @@ -133,7 +185,7 @@ def move_up(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def move_down(request): playlist_song = get_object_or_404(PlaylistSong, id=request.POST.get('id')) if playlist_song.user != request.user and not request.user.has_perm('queues.can_move'): @@ -143,7 +195,7 @@ def move_down(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def cancel(request): playlist_song = get_object_or_404(PlaylistSong, id=request.POST.get('id')) if playlist_song.user != request.user and not request.user.has_perm('queues.can_cancel'): @@ -154,7 +206,7 @@ def cancel(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def request(request): queue = request.user.queue song = get_object_or_404(Song, id=request.POST.get('id'), deleted=False) @@ -166,7 +218,7 @@ def request(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def upload(request): files = request.FILES.getlist('file[]') artists = request.POST.getlist('artist[]') @@ -192,7 +244,7 @@ def upload(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def volume_down(request): if not request.user.has_perm('queues.can_control_volume'): return HttpResponseForbidden() @@ -202,7 +254,7 @@ def volume_down(request): @require_http_methods(["POST"]) -@login_required +@api_auth_required def volume_up(request): if not request.user.has_perm('queues.can_control_volume'): return HttpResponseForbidden()