Tastypie: autenticación para GET y anónimo para POST

Utilizo Django / Tastypie para administrar mi colección de usuarios.

¿Es posible permitir a los usuarios anónimos realizar POST en la API (al crear un nuevo usuario en algún punto final) y restringir a los usuarios autenticados para OBTENER solo a sus propios usuarios, pero no a todos los usuarios?

Gracias por tu ayuda.

Descubrí que lo más fácil era hacer una subclase de la clase de autenticación que estoy usando. Simplemente anule el método is_authenticated para devolver True cuando el método es POST.

 class AnonymousPostAuthentication(BasicAuthentication): """ No auth on post / for user creation """ def is_authenticated(self, request, **kwargs): """ If POST, don't check auth, otherwise fall back to parent """ if request.method == "POST": return True else: return super(AnonymousPostAuthentication, self).is_authenticated(request, **kwargs) 

is_valid mi validación en una subclase de Validation y is_valid .

Hago el filtrado GET de la misma manera que Sampson lo hace arriba.

Sí, es posible hacer ambas cosas.

Este es un ejemplo simple de cómo permitiría a un usuario autenticado OBTENER solo su propio usuario JSON y no de todos los demás usuarios (asumiendo que está utilizando la infraestructura de usuario integrada de Django):

 # In api.py (or resource.py): ... from tastypie.resources import ModelResource from tastypie import fields from models import * from django.contrib.auth.models import User, Group from tastypie.authentication import BasicAuthentication from tastypie.authorization import DjangoAuthorization ... # REST endpoint for authenticating user accounts class UserResource(ModelResource): class Meta: queryset = User.objects.all() resource_name = 'auth/user' list_allowed_methods = ['get'] detail_allowed_methods = ['get'] authentication = BasicAuthentication() authorization = DjangoAuthorization() def apply_authorization_limits(self, request, object_list): return object_list.filter(username=request.user) 

Y aquí hay un ejemplo simple de cómo permitiría que un usuario anónimo haga POST para crear un nuevo usuario (Advertencia: esto no usa Tastypie, estrictamente hablando)

 # In views.py: ... from django.http import HttpResponse from django.contrib.auth.models import User, Group from django.contrib.auth import authenticate from django.http import Http404 from django.utils import timezone from models import * from api import * from django.utils import simplejson ... # REST endpoint for user registration # Enforces server-side mediation (input validation) # On failure, raises Http404 # On success, redirects to registration success page def register_user(request): if request.method != 'POST': raise Http404('Only POSTs are allowed') # acquire params username = request.POST['username'] password = request.POST['password'] repeatpw = request.POST['repeatpw'] first_name = request.POST['first_name'] last_name = request.POST['last_name'] # Server-side mediation to check for invalid input if username == '' or username is None: raise Http404('Server-side mediation: Invalid Username') if len(username) > 30: raise Http404('Server-side mediation: username must be 30 characters or fewer') if len(first_name) > 30: raise Http404('Server-side mediation: first name must be 30 characters or fewer') if len(last_name) > 30: raise Http404('Server-side mediation: last name msut be 30 characters or fewer') if len(password) < 4: raise Http404('Server-side mediation: Password too short') if password != repeatpw: raise Http404('Server-side mediation: Password Mismatch') # This try-except block checks existence of username conflict try: test_user_exists = User.objects.get(username__exact=username) if test_user_exists != None: raise Http404('Server-side mediation: Username exists') except User.DoesNotExist: pass # Input passes all tests, proceed with user creation user = User.objects.create_user(username, 'default@nomail.com', password) group = Group.objects.get(name='Standard') user.first_name = first_name user.last_name = last_name user.groups.add(group) user.is_staff = False user.save() # Build confirmation JSON confirmation = { 'action': 'register_user', 'username': username, 'success': 'yes', } json_return = simplejson.dumps(confirmation) # return JSON of the success confirmation return HttpResponse(json_return, mimetype='application/json') 

Basado en eso, aquí hay un script de cómo podría crear un nuevo usuario a través del punto final REST utilizando curl:

 #!/bin/bash echo "Usage: ./register_user username password repeatpw first_name last_name" curl -v -d "username=$1&password=$2&repeatpw=$3&first_name=$4&last_name=$5" http://127.0.0.1:8000/register_user/ > result