Django-fr

Forum

#1 21-07-2012 11:00:03

sucrette
Membre
Inscription : 20-07-2012
Messages : 5

Problème de permission (?)

Bonjour à toutes et tous,

Tout d'abord, étant totalement débutante dans l'univers Django, je m'excuse par avance des énormités que je vais forcément proférer.

Je dois construire un site gérant deux niveaux d'utilisateurs : des "lecteurs", qui peuvent uniquement lire les données d'une base de données XML (peu importe pourquoi XML plutôt que d'utiliser le serveur SQL de Django) et des "rédacteurs", qui pourront modifier le contenu de cette base.

Le site est "privé", en ce sens qu'il est nécessaire de se logger pour y accéder, et n'est de fait pas accessible aux utilisateurs anonymes.

J'aimerais que la page principale du site soit différente en fonction du type d'utilisateur : tout simplement, s'il s'agit d'un "rédacteur", que deux liens "créer" et "éditer" soient ajoutés.

Pour ce faire, j'ai créé via le shell mes deux groupes "lecteur" et "redacteur", ma permission "creation_modification", ai ajouté cette dernière au groupe "redacteur et ai créé deux utilisateurs tests (un lecteur et un redacteur). Dans ma template principale, j'ai ajouté la condition suivante :

(...)
{% if perms.BaseXML.creation_modification %}
<li class="puceIntermediaire"><a href="#">Editer</a></li>
<li class="puceIntermediaire"><a href="#">Créer</a></li>
{% endif %}
(...)

Cela marche effectivement : quand je me connecte en tant que lecteur, ces deux options ne figurent pas dans ma liste, et quand je me connecte en tant que rédacteur, elles sont bien présentes. Je précise que toutes les fonctions de mes views sont précédées du décorateur @login_required.

Forte de ce "succès", j'ai voulu étoffer un peu ma template en ajoutant un lien permanent vers la page d'accueil. J'ai donc rajouté la ligne suivante :

<li class="puceIntermediaire"><a href="/MonSite/Principale">Créer</a></li>

Or, quand je me connecte en tant que rédacteur et que je clique sur ce lien, la page d'accueil est rechargée, mais sans les options liées à la permission "creation_modification"... En faisant quelques test, j'ai cru comprendre que j'étais automatiquement passé d'une session rédacteur à une session anonymous user... Pourquoi ?

J'avoue être un peu perdue, si quelqu'un pouvait m'expliquer ?

Hors ligne

#2 21-07-2012 13:13:48

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Problème de permission (?)

Salut,

Pour le passage en anonyme, je ne saurais te dire en l'état parce que par
défaut, tu ne te fait pas déconnecter d'une session comme ça. En tout cas ça
ne vient pas directement de @login_required qui ne fait que rediriger vers la
page de login lorsqu'un utilisateur anonyme essaye d'accéder à une ressource
protégée. Peut être a tu perdu ton cookie de session pendant tes tests.

Par contre à propos de ton lien :

  <li class="puceIntermediaire"><a href="/MonSite/Principale">Créer</a></li>

À part si tu l'a spécifié explicitement sans slash de fin dans tes urls (ou une
option particulière dans les settings pour les ignorer), ton lien devrait être
:

  /MonSite/Principale/

Si tu regardes dans tes logs, tu verras qu'en accédant à
"/MonSite/Principale", django te redirige à chaque fois vers
"/MonSite/Principale/".

Hors ligne

#3 21-07-2012 19:45:23

ksamuel
Modérateur
Inscription : 22-06-2012
Messages : 40
Site Web

Re : Problème de permission (?)

Bonjour,

Merci de poster:

- le code de vos views;
- les templates;
- urls.py;
- un dump json de vos permissions, groupes et utilisateurs (manage.py dumpdata).

(Utilisez un pastebin pour cela)

Qu'est-ce que vous utilisez pour l'authentification ? Quelles vues ? Comment ?

@+

Dernière modification par ksamuel (21-07-2012 19:45:57)

Hors ligne

#4 22-07-2012 10:18:34

sucrette
Membre
Inscription : 20-07-2012
Messages : 5

Re : Problème de permission (?)

Merci beaucoup pour vos réponses.

Pour David : merci pour la correction sur les urls.

Pour ksamuel : je vous poste ça demain, dès que j'aurai à nouveau accès à mon ordinateur de développement.

Hors ligne

#5 23-07-2012 07:46:48

sucrette
Membre
Inscription : 20-07-2012
Messages : 5

Re : Problème de permission (?)

Le fichier views.py de mon application "Connexion" :

# -*- coding:utf-8 -*-

from django.http import HttpResponse, HttpResponseRedirect
from django.template import Context, loader, RequestContext
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.core.context_processors import csrf
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

def Identification(request):
    try :
        nom = request.POST['nom']
    except :
        return(render_to_response('Identification.html', context_instance=RequestContext(request)))
    else :
        password = request.POST['password']    
        utilisateur = authenticate(username=nom, password=password)
        if utilisateur is not None :
            if utilisateur.is_active:
                login(request, utilisateur)
                #return(render_to_response('Principale.html', {'nom':nom}, context_instance=RequestContext(request)))
                return(HttpResponseRedirect(reverse('Metalangue.Interrogation.views.Principale')))
            else :
                return(render_to_response('Identification.html', {'erreur':'Votre compte a été désactivé'}, context_instance=RequestContext(request)))
        else :    
            return(render_to_response('Identification.html', {'erreur':'Login et/ou mot de passe incorrect(s)'}, context_instance=RequestContext(request)))

@login_required(login_url='/Metalangue/Connexion/')
def Deconnexion(request):
    logout(request)
    return(HttpResponseRedirect(reverse('Metalangue.Connexion.views.Identification')))

Le fichier views.py de mon application "Interrogation" :

# -*- coding:utf-8 -*-

from django.http import HttpResponse, HttpResponseRedirect
from django.template import Context, loader, RequestContext
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.core.context_processors import csrf
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

@login_required(login_url='/Metalangue/Connexion/')
def Principale(request):
    """
    Simple test pour l'instant.
    """
    return(render_to_response('Principale.html'))

Ma template "BASE.html" :

{% load staticfiles %}

<!DOCTYPE html>
<html lang="fr">
<head>
 <meta charset="utf-8"/>
 <title>{% block title %}Metalangue | Connexion{% endblock %}</title>
 <link rel="stylesheet" href="{% static 'Interrogation/style.css' %}"/>
</head>
<body>

  <div id="logo"><a href="/Metalangue/Principale"><img src="{% static 'Interrogation/logo.png' %}" alt="logo"/></a></div>

 <header>
  <div id="listeHorizontale">
   <div id="centrageLien">
    <a class="puceHorizontale" href="#">Contact</a>
    <a class="puceHorizontale" href="#">À propos</a>
    <a class="puceHorizontale" href="#">Lien 3</a>
    <a class="puceHorizontale" href="#">Lien 4</a>
    <a class="puceHorizontale" href="#">Lien 5</a>
   </div>
  </div>
 </header>

 <nav>
  <ul>
   <li id="puceInitiale">Recherche</li>
   <li id="puceInitiale2">
    <form method="get" action="#">
      <input type="text" name="terme" id="terme" size="6"/> 
    </form>
   </li>
   <li class="puceIntermediaire"><a href="/Metalangue/Principale/">Accueil</a></li>
   <li class="puceIntermediaire"><a href="/Metalangue/Deconnexion/">Déconnexion</a></li>
   <li class="puceIntermediaire"><a href="#">Consulter</a></li>
   {% if perms.BaseXML.creation_modification %}
   <li class="puceIntermediaire"><a href="#">Éditer</a></li>
   <li class="puceIntermediaire"><a href="#">Créer</a></li>   
   {% endif %}     
  </ul>
 </nav>

 <section id="corps">
{% block corps %}
{% endblock %}
 </section>

</body>
</html>

Ma template 'Identification.html' :

{% extends 'BASE_anter.html' %}

{% block title %}Metalangue | Connexion{% endblock %}

{% block corps %}
  <form method="post" action=".">
  {% csrf_token %}
  <fieldset>
  <legend>Connexion à la base Métalangue</legend>
  <p>
  <label for="nom">Nom d'utilisateur</label>
  <input type="text" name="nom" id="nom" size="30" maxlength="30" required autofocus/>
  </p>
  <p>
  <label for="password">Mot de passe</label>
  <input type="password" name="password" id="password" size="30" required/>
  </p>
  <p>
  <input type="submit" value="Se connecter"></input>
  </p>
  </fieldset>
  </form>
{% endblock %}

Mon urls.py :

from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url('^Metalangue/Connexion/$', 'Metalangue.Connexion.views.Identification'),
    url('^Metalangue/Deconnexion/$', 'Metalangue.Connexion.views.Deconnexion'),
    url('^Metalangue/Principale/$', 'Metalangue.Interrogation.views.Principale'),
    url(r'^Metalangue/admin/', include(admin.site.urls)),
)

Et le 'dump' demandé :

[{"pk": 4, "model": "contenttypes.contenttype", "fields": {"model": "contenttype", "name": "content type", "app_label": "contenttypes"}}, {"pk": 8, "model": "contenttypes.contenttype", "fields": {"model": "fiche", "name": "fiche", "app_label": "BaseXML"}}, {"pk": 2, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "auth"}}, {"pk": 7, "model": "contenttypes.contenttype", "fields": {"model": "logentry", "name": "log entry", "app_label": "admin"}}, {"pk": 1, "model": "contenttypes.contenttype", "fields": {"model": "permission", "name": "permission", "app_label": "auth"}}, {"pk": 5, "model": "contenttypes.contenttype", "fields": {"model": "session", "name": "session", "app_label": "sessions"}}, {"pk": 6, "model": "contenttypes.contenttype", "fields": {"model": "site", "name": "site", "app_label": "sites"}}, {"pk": 3, "model": "contenttypes.contenttype", "fields": {"model": "user", "name": "user", "app_label": "auth"}}, {"pk": "1b3f42168b0bc563f2614a87402fbf08", "model": "sessions.session", "fields": {"expire_date": "2012-08-03T14:53:44Z", "session_data": "MDA3OGU1ZTA1YjA1Y2EzYjI2YWZiYmY1ZTE0MDc2YmY4Mzc1MjFlOTqAAn1xAS4=\n"}}, {"pk": "3e0512a26d530d4abd3935555c57dc8b", "model": "sessions.session", "fields": {"expire_date": "2012-07-31T14:21:13Z", "session_data": "MDA3OGU1ZTA1YjA1Y2EzYjI2YWZiYmY1ZTE0MDc2YmY4Mzc1MjFlOTqAAn1xAS4=\n"}}, {"pk": "598a65482f1ffb33da92f9ce68631742", "model": "sessions.session", "fields": {"expire_date": "2012-08-06T06:24:16Z", "session_data": "MDA3OGU1ZTA1YjA1Y2EzYjI2YWZiYmY1ZTE0MDc2YmY4Mzc1MjFlOTqAAn1xAS4=\n"}}, {"pk": "71438ed36716a87d6ce7b04ae8420218", "model": "sessions.session", "fields": {"expire_date": "2012-08-03T16:48:17Z", "session_data": "ZDQ2NTAxZWJiYmFlNGYyYjI4ZjY2MGY2NWYzZjJiZGZjNmY5OTNjNDqAAn1xAShVEl9hdXRoX3Vz\nZXJfYmFja2VuZHECVSlkamFuZ28uY29udHJpYi5hdXRoLmJhY2tlbmRzLk1vZGVsQmFja2VuZHED\nVQ1fYXV0aF91c2VyX2lkcQSKAQl1Lg==\n"}}, {"pk": "b6bf59ecc2c82fc4c0e54ee9fa873df7", "model": "sessions.session", "fields": {"expire_date": "2012-08-02T15:30:24Z", "session_data": "ZWRiZDMzYWNkN2RkNzg0YjljNTgxMzQ4YTNiNDg2NjczNzU4YTQxODqAAn1xAShVCnRlc3Rjb29r\naWVVBndvcmtlZFUSX2F1dGhfdXNlcl9iYWNrZW5kcQJVKWRqYW5nby5jb250cmliLmF1dGguYmFj\na2VuZHMuTW9kZWxCYWNrZW5kcQNVDV9hdXRoX3VzZXJfaWRxBIoBCHUu\n"}}, {"pk": "c2d6565732afb5119b4cba045152d79a", "model": "sessions.session", "fields": {"expire_date": "2012-08-04T09:19:04Z", "session_data": "MTA0MDZlZGI3YTU1NTAyZmE4ODhhMmE0MWVjMjk5YWQ1Nzk0NWQ1NzqAAn1xAShVDV9hdXRoX3Vz\nZXJfaWSKAQlVEl9hdXRoX3VzZXJfYmFja2VuZFUpZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5k\ncy5Nb2RlbEJhY2tlbmRxAnUu\n"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 7}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 22, "model": "auth.permission", "fields": {"codename": "add_fiche", "name": "Can add fiche", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_fiche", "name": "Can change fiche", "content_type": 8}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "creation_modification", "name": "creation_modification", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_fiche", "name": "Can delete fiche", "content_type": 8}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 4}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 5}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 6}}, {"pk": 1, "model": "auth.group", "fields": {"name": "lecteurs", "permissions": []}}, {"pk": 2, "model": "auth.group", "fields": {"name": "redacteurs", "permissions": [25]}}, {"pk": 1, "model": "auth.user", "fields": {"username": "joel", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": true, "last_login": "2012-07-23T06:23:41Z", "groups": [], "user_permissions": [], "password": "pbkdf2_sha256$10000$nX2snmwZT1cC$zFybGiAw0aftMchPhN5qilNElktGlVq9mNeBVHjlNF8=", "email": "joeline_2@hotmail.com", "date_joined": "2012-07-17T12:29:36Z"}}, {"pk": 8, "model": "auth.user", "fields": {"username": "lecteur", "first_name": "", "last_name": "", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-07-20T16:19:26Z", "groups": [1], "user_permissions": [], "password": "pbkdf2_sha256$10000$BEDmbwNhWFHA$4pcuoeV6o1zxy7htkN+L1zTFHC5I0A9DMjSnlZ+pbO4=", "email": "", "date_joined": "2012-07-19T13:07:32Z"}}, {"pk": 9, "model": "auth.user", "fields": {"username": "redacteur", "first_name": "", "last_name": "", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-07-23T06:24:07Z", "groups": [2], "user_permissions": [], "password": "pbkdf2_sha256$10000$hUC1ziiUb3qL$OFcT9775GVXt+48IKqzYDmch3erVi5LeZ1QS9eZ9bYI=", "email": "", "date_joined": "2012-07-19T13:08:01Z"}}]

Pour résumer, pour l'authentification, j'utilise donc un simple formulaire en méthode post ; si l'utilisateur a envoyé des champs, je tente de l'authentifier puis de le logger, sinon je le renvoie sur la page de connexion.

A noter que dans ma première views.py, j'ai remplacé mon render_to_response initial (ligne commentée) par un httpresponseredirect ; désormais, cela ne marche même plus, je ne vois plus les options supplémentaires s'afficher dans ma page.

Hors ligne

#6 25-07-2012 07:08:20

sucrette
Membre
Inscription : 20-07-2012
Messages : 5

Re : Problème de permission (?)

Personne n'a une idée du problème ?

Hors ligne

#7 25-07-2012 10:37:08

ksamuel
Modérateur
Inscription : 22-06-2012
Messages : 40
Site Web

Re : Problème de permission (?)

Globalement votre code est bon, pour quelqu'un qui débute en Django, c'est assez rare pour le souligner. J'apprécie également que votre question soit bien posée, et que vous fournissiez tous les éléments demandés.

Il est très probable que votre problème vienne du fait que Principale() n'utilise pas RequestContext comme le fait Identification(). RequestContext est en effet responsable de la présence de la variable "perms" dans un template, et vous vous appuyez dessus pour vérifier les permissions.

Si vous utilisez Django 1.4, vous pouvez remplacer render_to_response() par render() fait exactement la même chose, mais utilise RequestContext par défaut.

Quelques conseils pour finir:

- les vues sont des fontions, et en Python le nom des fonctions est par convention écrit en minuscule, séparé par des underscore (def ma_fontion());
- je vous déconseille d'utiliser des majuscules dans les URLs, à moins d'avoir des besoins spécifiques comme mimer une API ou respecter une spécification;
- il existe déjà des fonctions d'authentification dans Django, la votre est bien codée, mais utiliser (r'^Metalangue/Connexion/$', 'django.contrib.auth.views.login', {'template_name': 'Identification.html''}), à la place de url('^Metalangue/Connexion/$', 'Metalangue.Connexion.views.Identification') vous épargnera non seulement le besoin de coder/débugguer/maintenir Identification(), mais cela permettra aussi d'éliminer cette fonction comme suspect dans les problèmes de login (on est pas à l'abris d'un petit détail qui nous échappe)

Hors ligne

#8 26-07-2012 07:19:03

sucrette
Membre
Inscription : 20-07-2012
Messages : 5

Re : Problème de permission (?)

Merci beaucoup Ksamuel,

C'était effectivement le problème. Je prends également bonne note de tous vos conseils pour maintenir la propreté du code.

Dernière modification par sucrette (26-07-2012 07:19:16)

Hors ligne

Pied de page des forums