From 782ed58f9b1d9ea3a3cd3aac11db81239555e808 Mon Sep 17 00:00:00 2001 From: Thomas NOEL Date: Thu, 16 Jan 2014 17:07:15 +0100 Subject: [PATCH] pfidp/users_admin: show a user; csv export --- virtualenv/pfidp/settings.py | 3 ++ .../pfidp/templates/users_admin/index.html | 7 +-- .../pfidp/templates/users_admin/read.html | 44 ++++++++++++++++ .../pfidp/templates/users_admin/users.csv | 2 + virtualenv/pfidp/users_admin/pfusers.py | 50 ++++++++++++++++--- virtualenv/pfidp/users_admin/urls.py | 1 + virtualenv/pfidp/users_admin/views.py | 39 ++++++++++++--- 7 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 virtualenv/pfidp/templates/users_admin/read.html create mode 100644 virtualenv/pfidp/templates/users_admin/users.csv diff --git a/virtualenv/pfidp/settings.py b/virtualenv/pfidp/settings.py index 0eb9ba4..824a1b1 100644 --- a/virtualenv/pfidp/settings.py +++ b/virtualenv/pfidp/settings.py @@ -321,6 +321,9 @@ PF_CONFIG_XML = '/conf/config.xml' # user_admins params +# store generated password here +CLEAR_PASSWORD_DIR = '/var/db/univnautes/pfidp/passwords' + # maximum expiration (0 to disable) IDP_UA_MAX_EXPIRES = 7 diff --git a/virtualenv/pfidp/templates/users_admin/index.html b/virtualenv/pfidp/templates/users_admin/index.html index 041bdf5..acbbf2d 100644 --- a/virtualenv/pfidp/templates/users_admin/index.html +++ b/virtualenv/pfidp/templates/users_admin/index.html @@ -16,8 +16,8 @@
- - + +
@@ -52,7 +52,7 @@ {% for user in users.values|dictsort:"name" %} - {{ user.name }} + {{ user.name }} {% if 'univnautes-idp-multiple' in user.priv %} — multiple{% endif %} {% if user.disabled %} — désactivé{% endif %} {% if user.ttl == 0 %} — expiré{% endif %} @@ -84,6 +84,7 @@ +
diff --git a/virtualenv/pfidp/templates/users_admin/read.html b/virtualenv/pfidp/templates/users_admin/read.html new file mode 100644 index 0000000..48ca849 --- /dev/null +++ b/virtualenv/pfidp/templates/users_admin/read.html @@ -0,0 +1,44 @@ +{% extends "users_admin/base.html" %} +{% load i18n %} +{% load staticfiles %} + +{% block title %}Utilisateur {{ user.name}}{% endblock %} + +{% block content %} + +

Utilisateur <{{ user.name }}>

+ + +
+
Login
{{ user.name }} + {% if user.disabled %} + — désactivé + {% endif %} +
+
Nom complet
{{ user.descr }} 
+
Expiration
{{ user.expires }} — + {% if user.ttl %}{{user.ttl}} jour{% if user.ttl > 1 %}s{% endif %}{% else %}expiré{% endif %}
+ {% if user.password %} +
Mot de passe
+ (cliquer ici pour l'afficher) + +
+ {% endif %} +
+
+ +
+ Retour à la liste + Modifier l'utilisateur + {% if user.disabled %} + Activer l'utilisateur + {% else %} + Désactiver l'utilisateur + {% endif %} + Supprimer l'utilisateur +
+ +{% endblock %} diff --git a/virtualenv/pfidp/templates/users_admin/users.csv b/virtualenv/pfidp/templates/users_admin/users.csv new file mode 100644 index 0000000..ecaaa46 --- /dev/null +++ b/virtualenv/pfidp/templates/users_admin/users.csv @@ -0,0 +1,2 @@ +"login","nom complet","expiration","mot de passe"{% for user in users %} +"{{ user.name|addslashes }}","{{ user.descr|safe|addslashes }} ","{{ user.expires|date:"c" }}","{{ user.password|default_if_none:"-"|safe|addslashes }} "{% endfor %} diff --git a/virtualenv/pfidp/users_admin/pfusers.py b/virtualenv/pfidp/users_admin/pfusers.py index 7685339..4148036 100644 --- a/virtualenv/pfidp/users_admin/pfusers.py +++ b/virtualenv/pfidp/users_admin/pfusers.py @@ -1,8 +1,12 @@ import xml.etree.ElementTree as ET try: from django.conf import settings + PF_CONFIG_XML = settings.PF_CONFIG_XML + CLEAR_PASSWORD_DIR = settings.CLEAR_PASSWORD_DIR except ImportError: - settings = None + PF_CONFIG_XML = '/conf/config.xml' + CLEAR_PASSWORD_DIR = '/var/db/univnautes/pfidp/passwords' + import datetime import subprocess import syslog @@ -11,6 +15,7 @@ import htmlentitydefs import re import random import fnmatch +import os pattern = re.compile("&(\w+?);") @@ -25,15 +30,41 @@ def html_entity_decode(string): def configxml(): - if settings: - f = open(settings.PF_CONFIG_XML,'r') - else: - f = open('/conf/config.xml','r') + f = open(PF_CONFIG_XML,'r') root = ET.fromstring(f.read()) f.close() return root -def get_all_pfusers(filter=None): +def create_password(username): + if not os.path.exists(CLEAR_PASSWORD_DIR): + os.makedirs(CLEAR_PASSWORD_DIR) + password = ''.join([random.choice('23456789ABCDEFGHJLMNPQRSTUVWXZabcdefghjkmnpqrstuvwxyz') + for x in range(random.randint(6,9))]) + filename = os.path.join(CLEAR_PASSWORD_DIR, 'user-%s' % username) + f = open(filename, 'wb') + f.write(password) + f.close() + return password + +def read_password(username): + filename = os.path.join(CLEAR_PASSWORD_DIR, 'user-%s' % username) + try: + f = open(filename, 'rb') + password = f.read() + f.close() + return password + except: + return None + +def delete_password(username): + filename = os.path.join(CLEAR_PASSWORD_DIR, 'user-%s' % username) + try: + os.unlink(filename) + except: + pass + + +def get_all_pfusers(filter=None, with_password=False): xml_users = configxml().findall('system/user') if xml_users is None: return {} @@ -54,6 +85,9 @@ def get_all_pfusers(filter=None): user['priv'] = set([priv.text for priv in xml_user.findall('priv')]) + if with_password: + user['password'] = read_password(user['name']) + expires = user.get('expires') if expires: try: @@ -136,8 +170,7 @@ def create(username, password, expires, disabled=False, descr='', multiple=False if multiple: privs += ',univnautes-idp-multiple' if not password: - password = ''.join([random.choice('23456789ABCDEFGHJLMNPQRSTUVWXZabcdefghjkmnpqrstuvwxyz') - for x in range(random.randint(6,9))]) + password = create_password(username) return call('create', name=username, password=password, expires=expires_str, disabled=disabled_str, @@ -166,6 +199,7 @@ def update(username, password, expires, disabled, descr, multiple): if multiple: privs += ',univnautes-idp-multiple' if password: + delete_password(username) return call('update', name=username, password=password, expires=expires_str, disabled=disabled_str, diff --git a/virtualenv/pfidp/users_admin/urls.py b/virtualenv/pfidp/users_admin/urls.py index c5e10b8..bd026a2 100644 --- a/virtualenv/pfidp/users_admin/urls.py +++ b/virtualenv/pfidp/users_admin/urls.py @@ -6,6 +6,7 @@ import views urlpatterns = patterns('', (r'^$', login_required(views.index)), (r'^create$', login_required(views.create)), + (r'^read/(?P[a-z0-9\.\-_]+)$', login_required(views.read)), (r'^update/(?P[a-z0-9\.\-_]+)$', login_required(views.update)), (r'^delete/(?P[a-z0-9\.\-_]+)$', login_required(views.delete)), (r'^desactivate/(?P[a-z0-9\.\-_]+)$', login_required(views.desactivate)), diff --git a/virtualenv/pfidp/users_admin/views.py b/virtualenv/pfidp/users_admin/views.py index 8b1d295..b490038 100644 --- a/virtualenv/pfidp/users_admin/views.py +++ b/virtualenv/pfidp/users_admin/views.py @@ -4,8 +4,9 @@ from django.conf import settings from django.shortcuts import render_to_response, redirect from django.contrib.auth.decorators import user_passes_test -from django.template import RequestContext +from django.template import RequestContext, loader, Context from django.contrib import messages +from django.http import HttpResponse import pfusers from forms import UserForm, NewUserForm, ConfirmForm @@ -13,12 +14,17 @@ import datetime @user_passes_test(lambda user: user.is_staff, login_url='/logout') def index(request): - filter = request.GET.get('filter') + filter = request.GET.get('filter', None) + if filter is None: + filter = request.COOKIES.get('filter', None) context = { 'users': pfusers.get_all_pfusers(filter), 'filter': filter or '' } - return render_to_response('users_admin/index.html', - context, - context_instance=RequestContext(request)) + response = render_to_response('users_admin/index.html', + context, + context_instance=RequestContext(request)) + if filter is not None: + response.set_cookie('filter', filter) + return response @user_passes_test(lambda user: user.is_staff, login_url='/logout') def create(request): @@ -81,6 +87,16 @@ def create(request): { 'form': form, }, context_instance=RequestContext(request)) +@user_passes_test(lambda user: user.is_staff, login_url='/logout') +def read(request, name=None): + user = pfusers.get_all_pfusers(with_password=True).get(name, None) + if user == None: + messages.error(request, u'Utilisateur <%s> inconnu.' % name) + return redirect('..') + return render_to_response('users_admin/read.html', + { 'user': user, }, + context_instance=RequestContext(request)) + @user_passes_test(lambda user: user.is_staff, login_url='/logout') def update(request, name=None): user = pfusers.get_all_pfusers().get(name, None) @@ -204,6 +220,7 @@ ACTION_NAME = { 'delete': u'Suppression', 'desactivate': u'Désactivation', 'activate': u'Activation', + 'csv': u'Export CSV', } @user_passes_test(lambda user: user.is_staff, login_url='/logout') @@ -221,12 +238,14 @@ def multiple(request): if len(names) == 0: messages.warning(request, u'Sélectionnez au moins un utilisateur.') return redirect('.') - all_pfusers = pfusers.get_all_pfusers() + all_pfusers = pfusers.get_all_pfusers(with_password=(action=="csv")) try: users = [ all_pfusers[name] for name in names ] except KeyError: messages.error(request, u'Au moins un utilisateur inconnu dans la liste.') return redirect('.') + if action == "csv": + return csv(users) request.session['univnautes_idpua_action'] = action request.session['univnautes_idpua_names'] = names form = ConfirmForm() @@ -267,3 +286,11 @@ def multiple(request): return redirect('.') +def csv(users): + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="users.csv"' + t = loader.get_template('users_admin/users.csv') + c = Context({ 'users': users, }) + response.write(t.render(c)) + return response +