Sto costruendo una semplice API usando django-tastypie. L'idea è che ho due risorse:Problemi con ForeignKey usando POST in Django-Tastypie
- Un Nota risorsa che rappresenta una nota lasciato da un utente. Solo l'utente che ha creato una nota può modificarlo.
- A Commento risorsa. I commenti possono essere lasciati su qualsiasi nota da qualsiasi utente.
TL; DR: Non sono in grado di limitare Nota editing per il creatore di una nota, pur consentendo a qualsiasi utente di commentare una nota.
Sto usando la seguente configurazione per l'autenticazione:
class CreatedByEditAuthorization(Authorization):
def is_authorized(self, request, object=None, **kwargs):
return True
def apply_limits(self, request, object_list):
if request and request.method != 'GET' and hasattr(request, 'user'):
return object_list.filter(created_by=request.user)
return object_list
Insomma, un utente è autorizzato solo per modificare gli oggetti di cui sono uguale alla proprietà created_by (possono modificare solo gli oggetti che hanno creato) .
Questo è legato come segue:
class NoteResource(ModelResource):
comments = fields.ToManyField('myapp.api.resources.CommentResource', 'comments', null=True, blank=True)
created_by = fields.ToOneField('account.api.resources.UserResource', 'created_by')
def obj_create(self, bundle, request, **kwargs):
return super(HapResource, self).obj_create(bundle, request, created_by=request.user)
class Meta:
queryset = Note.objects.all()
allowed_methods = ['get', 'put', 'post']
authorization = CreatedByEditAuthorization()
ecco, quando si crea un oggetto, allego automaticamente l'utente corrente all'attributo created_by
e collegarlo al l'autorizzazione appropriata.
Una risorsa Comment
A è una semplice e ha una risorsa ForeignKey
in una risorsa Note
.
Il problema è questo: se l'utente A crea una nota e l'utente B tenta di commentare che la nota, tastypie invia (o simula) una richiesta POST per modificare che la nota. Tale tentativo viene rifiutato poiché l'utente B non ha creato la nota, pertanto la creazione del commento non riesce.
La domanda è questa: c'è un modo per entrambi:
- Impedire tastypie dall'utilizzo di un POST per creare il reverse-relazione alla risorsa Nota o
- Modifica del regime di autorizzazione quindi Notes può essere modificato solo dal loro creatore, ma i commenti possono essere generati in generale?
Grazie in anticipo per eventuali approfondimenti.
Modifica: Ho una grossa hack grassa che può realizzare questo. Sono abbastanza sicuro che sia sicuro, ma non sono positivo; Cercherò di costruire alcune query per essere sicuro. Invece di usare fields.ForeignKey
in Comment
di relazionarsi con Note
, crea un campo personalizzato:
class SafeForeignKey(fields.ForeignKey):
def build_related_resource(self, value, request=None, related_obj=None, related_name=None):
temp = request.method
if isinstance(value, basestring):
request.method = 'GET'
ret = super(SafeForeignKey, self).build_related_resource(value, request, related_obj, related_name)
request.method = temp
return ret
Ogni volta che cerchiamo di costruire questa risorsa correlata, vi segnalo la richiesta in via GET
(in quanto ci aspettiamo da abbinare a una query SELECT
anziché UPDATE
che corrisponde a PUT
o POST
). Questo è davvero brutto e potenzialmente pericoloso se usato in modo errato, e spero in una soluzione migliore.
Modifica 2: Dalla lettura della fonte tastypie, per quanto posso dire non c'è modo di filtrare l'autorizzazione dalla query che verrà effettivamente inviata.
Un paio di domande - Stai usando contrib.comments? Stai usando l'autenticazione e l'autorizzazione? Ho quello che sembra essere un setup molto simile (senza sembrare CommentResource) che funziona bene quando si pubblica un nuovo commento su un altro oggetto utente. – JamesO
@JamesO No, i nostri commenti sono in qualche modo più ricchi di quanto offerto da contrib.comments (e vi sono altri dati associati a un post che presenta lo stesso problema). Al momento utilizziamo solo l'autenticazione integrata() (ad esempio, tutti sono autenticati). –
Hai postato questo come un problema su django-tastypie: https://github.com/toastdriven/django-tastypie/issues? Se tenta sinceramente di aggiornare un record genitore ogni volta che crei qualcosa relativo ad esso, è più vicino a un bug che a una funzionalità. –