0
votes

Restreindre un utilisateur à obtenir ou mettre à jour un objet créé par un utilisateur spécifique django

J'ai un modèle de tâche comme

    def get(self, request, id):
        task = Tasks.objects.get(id=id)
        if task:
            serializer = TasksSerializer(task, many=False)
            return Response(success_response(serializer.data, "Contact Information."
 status=status.HTTP_200_OK)

J'ai une vue comme

class Tasks(models.Model):
    made_by=models.ForeignKey(User , on_delete=models.CASCADE)
    title = models.CharField(max_length=100,null=True,blank=True)

Et un PUT de la même manière. Je veux vérifier uniquement l'utilisateur qui l'a créé peut y accéder . Existe-t-il un moyen intelligent de le faire? Je ne veux pas demander à nouveau de vérifier dans toutes les vues et par la suite.


4 commentaires

Utilisez-vous authentication_classes dans vos vues? Si tel est le cas, vous pouvez accéder aux Tâches liées à la classe de User en la référençant à partir de request.user.tasks.get .


Remplacez également made_by = models.ForeignKey (User, on_delete = models.CASCADE) par made_by = models.ForeignKey (User, related_name = "tasks", on_delete = models.CASCADE) .


@ Rfroes87 oui j'utilise l'authentification, mais je ne veux pas m'enregistrer partout comme ça ne sera pas le code DRY. Je veux faire quelque chose comme Decorator pour ça


Pouvez-vous ajouter votre classe de vue complète et votre classe de sérialiseur?


3 Réponses :


0
votes

il y a plusieurs façons de procéder, mais je pense que le plus simple est de tester le statut de l'utilisateur. c'est-à-dire

class AccountManager(BaseUserManager):

def create_user(self, password):
    # define regular creation process
    . . . 
    return user

def create_special_user(self, password):
    # define special creation process i.e.
    has_task_perms == True
    return user

un autre moyen plus compliqué serait de jouer avec les perms du modèle de compte standard et de définir les perms de 'tâche' sur false. c'est-à-dire

def has_task_perms(self):
    return False

et ensuite dans le processus de création d'utilisateur à travers n'importe quel type d'utilisateur a la capacité de donner des perms de tâche. La façon la plus courante que je connaisse pour ce faire est d'utiliser un gestionnaire de compte (un lapin entier en soi), c'est-à-dire

    def run_task(self, request, id):
         if request.user.made_by == 'Foo Bar'
            . . . .
            return Response(success_response ...
         else
            return Response(failure_response ...


0 commentaires

1
votes

Puisqu'il semble que vous utilisez des vues basées sur les classes, je vous suggère de remplacer la méthode dispatch de votre classe. Cette classe est exécutée à chaque fois que quelqu'un appelle la vue, quelle que soit la méthode.

Dans cette méthode de répartition, vous pouvez tout d'abord récupérer l'objet de tâche comme vous le faites dans la fonction get dans votre code actuel. Après cette étape, vous pouvez alors effectuer une vérification pour voir si le request.user est égal au made_by de l'objet .

Par exemple:

< pre> XXX

De plus, je suggérerais également d'utiliser le LoginRequiredMixin (source) pour s'assurer que seuls les utilisateurs connectés peuvent accéder à la vue. Cela pourrait éliminer les vérifications écrites personnalisées dans de nombreux cas.

Le PermissionRequiredMixin (source) est également un excellent choix lorsqu'il s'agit d'autorisations plus générales qui ne sont pas liées à des instances spécifiques.

Pour en savoir plus des autorisations spécifiques - personnalisées - vous pouvez également utiliser UserPassesTestMixin (source) pour écrire des vérifications dans des fonctions de test dédiées pour garder votre code plus propre.


5 commentaires

semble intéressant, vérifierait cela en temps. donc Au cas où pas besoin d'ajouter un décorateur?


@gamer Je ne pense pas que l'utilisation d'un décorateur dans cette situation serait la meilleure solution, bien que possible si vous le vouliez vraiment. Même si ce n'est pas toujours faisable ou la meilleure option, je suggérerais d'essayer d'utiliser autant que possible les fonctionnalités de base de Django. Par exemple, vous pouvez également ajouter un décorateur login_required à la fonction (qui est également une fonctionnalité intégrée de Django), mais personnellement, je vous déconseille car il existe déjà un mixin intégré qui le fait tout ce processus pour vous.


puis-je retourner quelque chose comme un message personnalisé au lieu de Http 404


@gamer Vous pouvez à coup sûr! Remplacez simplement la partie rise Http404 () par une redirection ou toute autre réponse http, comme le rendu d'un autre modèle.


il s'est produit quelque chose de louche. Je ne peux pas accéder à l'utilisateur dans la fonction de répartition en utilisant jwt, son utilisateur anon et dans la méthode PUT, cela fonctionne bien



0
votes

J'ai essayé tellement de solutions mais à la fin j'ai créé un décorateur comme celui-ci

def task_ownership_check(func):
    def wrapper(request,*args, **kwargs):
        print(kwargs['id'])
        try:
           task = Tasks.objects.get(id=kwargs['id'])
        except Tasks.DoesNotExist:
            return Response(failure_response(data={}, msg='No task matching query found'),
                            status=status.HTTP_404_NOT_FOUND)

        if args[0].user != task.todolist.for_user:
            return Response(failure_response(data={'error': 'You are not allowed to access this record'},
                                             msg='You are not allowed to access this record'),
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            return func(args[0], kwargs['id'])

    return wrapper

Je peux donc vérifier facilement en incluant @task_ownership_check sur n'importe quelle tâche


0 commentaires