pfidp/users_admin: show a user; csv export
This commit is contained in:
parent
64413a3041
commit
782ed58f9b
|
@ -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
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<div class="span4">
|
||||
<form method="get" action="" class="form-inline pull-right">
|
||||
<div class="input-prepend input-append">
|
||||
<span class="add-on"><a href="./"><i class="icon-remove-circle"></i></a></span>
|
||||
<input id="filter" type="text" name="filter" value="{{ filter }}" placeholder="Filtre (avec * et ?)"/>
|
||||
<span class="add-on"><a href="./?filter="><i class="icon-remove-circle"></i></a></span>
|
||||
<input id="filter" type="text" name="filter" value="{{ filter }}" style="color: red; font-weight: bold;" placeholder="Filtre (avec * et ?)"/>
|
||||
<input type="submit" value="Filtrer" class="btn" />
|
||||
</div>
|
||||
</form>
|
||||
|
@ -52,7 +52,7 @@
|
|||
{% for user in users.values|dictsort:"name" %}
|
||||
<tr {% if user.disabled or user.ttl == 0 %} class="disabled"{% endif %}>
|
||||
<td data-order-by="{{ user.name }}">
|
||||
<a href="update/{{ user.name }}" {% if user.disabled or user.ttl == 0 %} class="disabled"{% endif %}>{{ user.name }}</a>
|
||||
<a href="read/{{ user.name }}" {% if user.disabled or user.ttl == 0 %} class="disabled"{% endif %}>{{ user.name }}</a>
|
||||
{% 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 @@
|
|||
<option value="desactivate">Désactiver les utilisateurs choisis</option>
|
||||
<option value="activate">Activer les utilisateurs choisis</option>
|
||||
<option value="delete">Supprimer les utilisateurs choisis</option>
|
||||
<option value="csv">Exporter la liste en CSV</option>
|
||||
<!-- option value="expire">Changer la date d'expiration des utilisateurs choisis</option -->
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
{% extends "users_admin/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Utilisateur {{ user.name}}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Utilisateur <{{ user.name }}></h1>
|
||||
|
||||
<span style="font-size: 1.2em;">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Login</dt> <dd>{{ user.name }}
|
||||
{% if user.disabled %}
|
||||
— <strong>désactivé</strong>
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>Nom complet</dt> <dd>{{ user.descr }} </dd>
|
||||
<dt>Expiration</dt> <dd>{{ user.expires }} —
|
||||
{% if user.ttl %}{{user.ttl}} jour{% if user.ttl > 1 %}s{% endif %}{% else %}<strong>expiré</strong>{% endif %}</dd>
|
||||
{% if user.password %}
|
||||
<dt>Mot de passe</dt> <dd><span id="hidepass" style="display: none;">{{ user.password }}</span>
|
||||
<span id="showpass">(cliquer ici pour l'afficher)</span>
|
||||
<script>
|
||||
$('#showpass').click(function() {$('#hidepass').show(); $('#showpass').hide();});
|
||||
$('#hidepass').click(function() {$('#showpass').show(); $('#hidepass').hide();});
|
||||
</script>
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</span>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href=".." class="btn btn-primary"><i class="icon-list"></i> Retour à la liste</a>
|
||||
<a href="../update/{{ user.name }}" class="btn"><i class="icon-edit"></i> Modifier l'utilisateur</a>
|
||||
{% if user.disabled %}
|
||||
<a href="../activate/{{ user.name }}" class="btn"><i class="icon-play"></i> Activer l'utilisateur</a>
|
||||
{% else %}
|
||||
<a href="../desactivate/{{ user.name }}" class="btn"><i class="icon-pause"></i> Désactiver l'utilisateur</a>
|
||||
{% endif %}
|
||||
<a href="../delete/{{ user.name }}" class="btn btn-danger pull-right"><i class="icon-trash"></i> Supprimer l'utilisateur</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -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 %}
|
Can't render this file because it contains an unexpected character in line 1 and column 49.
|
|
@ -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,
|
||||
|
|
|
@ -6,6 +6,7 @@ import views
|
|||
urlpatterns = patterns('',
|
||||
(r'^$', login_required(views.index)),
|
||||
(r'^create$', login_required(views.create)),
|
||||
(r'^read/(?P<name>[a-z0-9\.\-_]+)$', login_required(views.read)),
|
||||
(r'^update/(?P<name>[a-z0-9\.\-_]+)$', login_required(views.update)),
|
||||
(r'^delete/(?P<name>[a-z0-9\.\-_]+)$', login_required(views.delete)),
|
||||
(r'^desactivate/(?P<name>[a-z0-9\.\-_]+)$', login_required(views.desactivate)),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Reference in New Issue