Add debian packaging
This commit is contained in:
parent
a2a3242889
commit
0cbbfc5cd8
|
@ -0,0 +1 @@
|
|||
OPTIONS="--port 4001"
|
|
@ -5,17 +5,17 @@
|
|||
# Required-Stop: $local_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Authentic IdP (Pr@tic)
|
||||
# Description: Authentic Identity Provider (with Pr@tic extension)
|
||||
# Short-Description: Authentic IdP (IFEF)
|
||||
# Description: Authentic Identity Provider (with IFEF extension)
|
||||
### END INIT INFO
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DESC="Authentic (+Pr@tic)"
|
||||
NAME=authentic-pratic
|
||||
DESC="Authentic (+IFEF)"
|
||||
NAME=authentic-ifef
|
||||
DAEMON=/usr/sbin/authenticctl
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
OPTIONS="--extra /usr/share/python-support/authentic-pratic/extra"
|
||||
OPTIONS="--extra /usr/share/python-support/authentic-ifef/extra"
|
||||
|
||||
# Gracefully exit if the package has been removed.
|
||||
test -x $DAEMON || exit 0
|
|
@ -1,15 +1,15 @@
|
|||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/authentic-pratic" ]; then
|
||||
update-rc.d authentic-pratic defaults >/dev/null
|
||||
if [ -x "/etc/init.d/authentic-ifef" ]; then
|
||||
update-rc.d authentic-ifef defaults >/dev/null
|
||||
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
|
||||
invoke-rc.d authentic-pratic start || exit $?
|
||||
invoke-rc.d authentic-ifef start || exit $?
|
||||
else
|
||||
/etc/init.d/authentic-pratic start || exit $?
|
||||
/etc/init.d/authentic-ifef start || exit $?
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
# Automatically added by dh_pysupport
|
||||
if [ "$1" = "configure" ] && which update-python-modules >/dev/null 2>&1; then
|
||||
update-python-modules -i /usr/share/python-support/authentic-pratic
|
||||
update-python-modules -i /usr/share/python-support/authentic-ifef
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,5 +1,5 @@
|
|||
# Automatically added by dh_installinit
|
||||
if [ "$1" = "purge" ] ; then
|
||||
update-rc.d authentic-pratic remove >/dev/null || exit $?
|
||||
update-rc.d authentic-ifef remove >/dev/null || exit $?
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,14 +1,14 @@
|
|||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/authentic-pratic" ]; then
|
||||
if [ -x "/etc/init.d/authentic-ifef" ]; then
|
||||
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
|
||||
invoke-rc.d authentic-pratic stop || exit $?
|
||||
invoke-rc.d authentic-ifef stop || exit $?
|
||||
else
|
||||
/etc/init.d/authentic-pratic stop || exit $?
|
||||
/etc/init.d/authentic-ifef stop || exit $?
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
# Automatically added by dh_pysupport
|
||||
if which update-python-modules >/dev/null 2>&1; then
|
||||
update-python-modules -c -i /usr/share/python-support/authentic-pratic
|
||||
update-python-modules -c -i /usr/share/python-support/authentic-ifef
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,2 +0,0 @@
|
|||
/etc/init.d/authentic-pratic
|
||||
/etc/ldap/schema/cdg59.schema
|
|
@ -1,17 +0,0 @@
|
|||
Package: authentic-pratic
|
||||
Version: 1.0.7
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
Depends: python (<< 2.5), python (>= 2.4), python-support (>= 0.2), authentic, python-ldap
|
||||
Installed-Size: 328
|
||||
Maintainer: Frederic Peters <fpeters@entrouvert.com>
|
||||
Description: Liberty Alliance Identity Server - Pr@tic Extension
|
||||
Authentic is a Liberty-compliant identity provider aiming to address a broad
|
||||
range of needs, from simple to complex setups. Its Liberty compliance relies
|
||||
on Lasso, a free (GNU GPL) implementation of the Liberty Alliance
|
||||
specifications.
|
||||
.
|
||||
It is a quixote application and is commonly runned inside Apache web server.
|
||||
.
|
||||
This package provides an extension to Authentic for Pr@tic specific features.
|
|
@ -1,23 +0,0 @@
|
|||
af710403211af4e3353b3aa9755ca87e usr/share/python-support/authentic-pratic/extra/pratic.py
|
||||
b0135901e1f38f5e52dbac9f426833d3 usr/share/python-support/authentic-pratic/extra/modules/services_ui.ptl
|
||||
2236ca43b6ccaf4dc556466ec456b068 usr/share/python-support/authentic-pratic/extra/modules/__init__.py
|
||||
e876c0cb7ce6cabf9914a4e0647a7413 usr/share/python-support/authentic-pratic/extra/modules/admin.ptl
|
||||
c1715a0ede0df8c48da35f42a5f70c57 usr/share/python-support/authentic-pratic/extra/modules/saml2.py
|
||||
aacd1462dfc10c45b1e00a13ff5cdcd7 usr/share/python-support/authentic-pratic/extra/modules/backoffice.ptl
|
||||
35f853a46594d7533b0256d0756acfbd usr/share/python-support/authentic-pratic/extra/modules/directory.py
|
||||
f1180dd2890095d68654a23cfd9bb499 usr/share/python-support/authentic-pratic/extra/modules/identities_ui.ptl
|
||||
b3da052a0e221c3b5217cdb3bf2a99e4 usr/share/python-support/authentic-pratic/extra/modules/root.ptl
|
||||
61bca76d2d7f1093f49d270d4b909736 usr/share/python-support/authentic-pratic/extra/modules/store.py
|
||||
70b2f67684d725e077cce308fcf58dea usr/share/python-support/authentic-pratic/extra/modules/sessions.py
|
||||
79b14f906aaecef8e10c05d6ea882982 usr/share/python-support/authentic-pratic/.version
|
||||
b7b41078dad08cc8a30f84dd1a858821 usr/share/locale/fr/LC_MESSAGES/pratic.mo
|
||||
624cf0d50f3b5de3dee54d1b284ac4f3 usr/share/doc/authentic-pratic/changelog.gz
|
||||
5e26bd0b3f505abe48145c640477d01c usr/share/doc/authentic-pratic/copyright
|
||||
747b47c0fdeea68525721041f64620fc usr/share/authentic/themes/pratic/admon-tip.png
|
||||
952c2420523acebc86616b51d76bcb63 usr/share/authentic/themes/pratic/deg.png
|
||||
09caf398658ea160aac106d6496f3804 usr/share/authentic/themes/pratic/desc.xml
|
||||
b3cada1c583ed17b1aedb20bca762106 usr/share/authentic/themes/pratic/template.ezt
|
||||
5dc7c3d0b91c243ea8504ef221438144 usr/share/authentic/themes/pratic/path18223.png
|
||||
feec7d22f2fdc7c0b6cdbb8a02d383ba usr/share/authentic/themes/pratic/lockscreen-bg.png
|
||||
e5259c303e69488d08cb6e5627d451f7 usr/share/authentic/themes/pratic/lockscreen.png
|
||||
34c1990c0a8232c6a4cd56539acad0fd usr/share/authentic/themes/pratic/authentic.css
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/authentic-pratic" ]; then
|
||||
update-rc.d authentic-pratic defaults >/dev/null
|
||||
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
|
||||
invoke-rc.d authentic-pratic start || exit $?
|
||||
else
|
||||
/etc/init.d/authentic-pratic start || exit $?
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
# Automatically added by dh_pysupport
|
||||
if [ "$1" = "configure" ] && which update-python-modules >/dev/null 2>&1; then
|
||||
update-python-modules -i /usr/share/python-support/authentic-pratic
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
# Automatically added by dh_installinit
|
||||
if [ "$1" = "purge" ] ; then
|
||||
update-rc.d authentic-pratic remove >/dev/null || exit $?
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/authentic-pratic" ]; then
|
||||
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
|
||||
invoke-rc.d authentic-pratic stop || exit $?
|
||||
else
|
||||
/etc/init.d/authentic-pratic stop || exit $?
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
# Automatically added by dh_pysupport
|
||||
if which update-python-modules >/dev/null 2>&1; then
|
||||
update-python-modules -c -i /usr/share/python-support/authentic-pratic
|
||||
fi
|
||||
# End automatically added section
|
|
@ -1,95 +0,0 @@
|
|||
#! /bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: authentic
|
||||
# Required-Start: $local_fs $network
|
||||
# Required-Stop: $local_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Authentic IdP (Pr@tic)
|
||||
# Description: Authentic Identity Provider (with Pr@tic extension)
|
||||
### END INIT INFO
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DESC="Authentic (+Pr@tic)"
|
||||
NAME=authentic-pratic
|
||||
DAEMON=/usr/sbin/authenticctl
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
OPTIONS="--extra /usr/share/python-support/authentic-pratic/extra"
|
||||
|
||||
# Gracefully exit if the package has been removed.
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
# Read config file if it is present.
|
||||
if [ -r /etc/default/$NAME ]
|
||||
then
|
||||
. /etc/default/$NAME
|
||||
fi
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service.
|
||||
#
|
||||
d_start() {
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
||||
--chuid www-data:www-data --make-pidfile --background --exec $DAEMON -- start $OPTIONS
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service.
|
||||
#
|
||||
d_stop() {
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service.
|
||||
#
|
||||
d_reload() {
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
|
||||
--make-pidfile --background --signal 1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting $DESC: $NAME"
|
||||
d_start
|
||||
echo "."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Stopping $DESC: $NAME"
|
||||
d_stop
|
||||
echo "."
|
||||
;;
|
||||
#reload)
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
# If the daemon responds to changes in its config file
|
||||
# directly anyway, make this an "exit 0".
|
||||
#
|
||||
# echo -n "Reloading $DESC configuration..."
|
||||
# d_reload
|
||||
# echo "done."
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented, move the "force-reload"
|
||||
# option to the "reload" entry above. If not, "force-reload" is
|
||||
# just the same as "restart".
|
||||
#
|
||||
echo -n "Restarting $DESC: $NAME"
|
||||
d_stop
|
||||
sleep 1
|
||||
d_start
|
||||
echo "."
|
||||
;;
|
||||
*)
|
||||
# echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -1,187 +0,0 @@
|
|||
# Schéma LDAP
|
||||
#
|
||||
|
||||
objectIdentifier Cdg59Root 1.1
|
||||
objectIdentifier Cdg59LDAP Cdg59Root:2
|
||||
objectIdentifier Cdg59LDAPAttribute Cdg59LDAP:1
|
||||
objectIdentifier Cdg59LDAPObjectClass Cdg59LDAP:2
|
||||
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:1 NAME 'cdg59siretCode'
|
||||
DESC 'Collectivity SIRET code'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SINGLE-VALUE)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:2 NAME 'cdg59direction'
|
||||
DESC 'Collectivity Direction'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:3 NAME 'cdg59isAdmin'
|
||||
DESC 'Admin or not'
|
||||
EQUALITY booleanMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:4 NAME 'cdg59isDisabled'
|
||||
DESC 'Acccount disabled or not'
|
||||
EQUALITY booleanMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:5 NAME 'cdg59sid'
|
||||
DESC 'Service Id'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:6 NAME 'cdg59siid'
|
||||
DESC 'Service Instance Id'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:7 NAME 'cdg59serviceType'
|
||||
DESC 'Service Type'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:8 NAME 'cdg59URL'
|
||||
DESC 'Generic URL'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:9 NAME 'cdg59metadataURL'
|
||||
DESC 'Service Metadata URL'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:10 NAME 'cdg59serviceAccesses'
|
||||
DESC 'Services an agent can access'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:11 NAME 'cdg59collectivitySirhCode'
|
||||
DESC 'Collectivity SIRH code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
|
||||
SINGLE-VALUE)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:12 NAME 'cdg59collectivitySirhLabel'
|
||||
DESC 'Collectivity SIRH Label'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:13 NAME 'cdg59regionCode'
|
||||
DESC 'Collectivity "Region" Code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:14 NAME 'cdg59departementCode'
|
||||
DESC 'Collectivity "Departement" Code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:15 NAME 'cdg59arrondissementCode'
|
||||
DESC 'Collectivity "Arrondissement" Code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:16 NAME 'cdg59cantonCode'
|
||||
DESC 'Collectivity "Canton" Code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:17 NAME 'cdg59inseeCode'
|
||||
DESC 'Collectivity INSEE Code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:18 NAME 'cdg59streetNumber'
|
||||
DESC 'Collectivity street number'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:19 NAME 'cdg59distOffice'
|
||||
DESC 'Collectivity distribution office'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:20 NAME 'cdg59addressCompl'
|
||||
DESC 'Collectivity complementary address infomation'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:21 NAME 'cdg59addressMention'
|
||||
DESC 'Collectivity particular mention on address'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:22 NAME 'cdg59agentSirhCode'
|
||||
DESC 'Collectivity SIRH code'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
|
||||
SINGLE-VALUE)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:23 NAME 'cdg59isGlobal'
|
||||
DESC 'Global service, or not'
|
||||
EQUALITY booleanMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:24 NAME 'cdg59ssoRelayState'
|
||||
DESC 'URL for redirection after a single sign on'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:25 NAME 'cdg59lastConnectionTime'
|
||||
DESC 'Last connection time'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27)
|
||||
|
||||
attributetype ( Cdg59LDAPAttribute:26 NAME 'cdg59lastConnectionDuration'
|
||||
DESC 'Last connection duration'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27)
|
||||
|
||||
|
||||
# CDG 59 Collectivity
|
||||
objectclass ( Cdg59LDAPObjectClass:1
|
||||
NAME 'cdg59collectivity'
|
||||
DESC 'CDG 59 Collectivity Objectclass'
|
||||
STRUCTURAL
|
||||
SUP organizationalUnit
|
||||
MAY ( cdg59siretCode $ cdg59collectivitySirhCode $ cdg59collectivitySirhLabel $ cn $ mail $ cdg59URL $ cdg59regionCode $ cdg59departementCode $ cdg59arrondissementCode $ cdg59cantonCode $ cdg59inseeCode $ cdg59streetNumber $ cdg59distOffice $ cdg59addressCompl $ cdg59addressMention ))
|
||||
|
||||
# CDG 59 Agent
|
||||
objectclass (Cdg59LDAPObjectClass:2
|
||||
NAME 'cdg59agent'
|
||||
DESC 'CDG 59 Agent Objectclass'
|
||||
STRUCTURAL
|
||||
SUP inetOrgPerson
|
||||
MUST ( uid )
|
||||
MAY ( cdg59isAdmin $ cdg59direction $ cdg59isDisabled $ cdg59serviceAccesses $ cdg59agentSirhCode $ cdg59lastConnectionTime $ cdg59lastConnectionDuration ))
|
||||
|
||||
# CDG 59 Service
|
||||
objectclass ( Cdg59LDAPObjectClass:3
|
||||
NAME 'cdg59service'
|
||||
DESC 'CDG 59 Service Objectclass'
|
||||
STRUCTURAL
|
||||
MUST ( cdg59sid )
|
||||
MAY ( cn $ description $ cdg59URL $ cdg59isGlobal $ cdg59metadataURL $ cdg59ssoRelayState ))
|
||||
|
||||
# CDG 59 Service Instance
|
||||
objectclass ( Cdg59LDAPObjectClass:4
|
||||
NAME 'cdg59serviceInstance'
|
||||
DESC 'CDG 59 Service Instance Objectclass'
|
||||
STRUCTURAL
|
||||
MUST ( cdg59siid )
|
||||
MAY ( cdg59serviceType $ cdg59URL $ cdg59metadataURL $ cdg59ssoRelayState ))
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB |
|
@ -1,147 +0,0 @@
|
|||
@import url(/css/authentic-common.css);
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
background: #eee;
|
||||
color: black;
|
||||
max-width: 50em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0072b8;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#page {
|
||||
border: 1px solid #0072b8;
|
||||
border-width: 0px 2px;
|
||||
background: white url(lockscreen.png) top right no-repeat;
|
||||
}
|
||||
|
||||
#top {
|
||||
margin-top: 20px;
|
||||
border-top: 2px solid #0072b8;
|
||||
background: #52bce5 url(lockscreen.png) top right no-repeat;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
#top h1 {
|
||||
margin: 1em 150px 0 10px;
|
||||
text-align: right;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding: 1em 2em 3em 2em;
|
||||
position: relative;
|
||||
/* background: url(lockscreen-bg.png) bottom right no-repeat; */
|
||||
background: url(path18223.png) 90% 0% no-repeat;
|
||||
}
|
||||
|
||||
p#breadcrumb {
|
||||
margin: 0 150px 0 0;
|
||||
font-size: 80%;
|
||||
background: #d9dde8 url(deg.png) top right repeat-y;
|
||||
padding: 0.5ex;
|
||||
}
|
||||
|
||||
#footer {
|
||||
border-bottom: 2px solid #0072b8;
|
||||
border-top: 1px solid #0072b8;
|
||||
background: #28a5dc;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#footer p {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
font-size: smaller;
|
||||
font-style: italic;
|
||||
padding: 1ex 1em 2px 0;
|
||||
}
|
||||
|
||||
|
||||
p#forgot-password {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 60px;
|
||||
}
|
||||
|
||||
p#register {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 100px;
|
||||
}
|
||||
|
||||
p#cookies {
|
||||
border: 1px solid #888;
|
||||
background: #ccf url(admon-tip.png) 5px 5px no-repeat;
|
||||
padding-left: 60px;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
ul.FederationsWidget {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.FederationsWidget a.terminate {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
margin-left: 5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
/* pratic stuff */
|
||||
|
||||
ul#services {
|
||||
width: 65%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
p#commands {
|
||||
clear: both;
|
||||
border-top: 2px solid #0072b8;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
div#platform-status {
|
||||
float: right;
|
||||
width: 25%;
|
||||
border: 2px solid #0072b8;
|
||||
background: white;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
-moz-border-radius: 5px;
|
||||
}
|
||||
|
||||
div#platform-status h3 {
|
||||
background: #0072b8;
|
||||
font-size: 100%;
|
||||
text-align: center;
|
||||
color: white;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div#platform-status div {
|
||||
padding: 0 1ex;
|
||||
}
|
||||
|
||||
div#platform-status p#report-issue {
|
||||
border-top: 2px solid #0072b8;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dl.profile dd {
|
||||
font-weight: bold;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 429 B |
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<theme name="pratic" version="1.0">
|
||||
<label>Pr@tic</label>
|
||||
<desc>Pr@tic Theme</desc>
|
||||
<author>Frederic Peters & artists</author>
|
||||
</theme>
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>[page_title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="[css]"/>
|
||||
[script]
|
||||
</head>
|
||||
<body[if-any onload] onload="[onload]"[end]>
|
||||
<div id="page">
|
||||
<div id="top"> <h1>Authentic</h1> </div>
|
||||
[if-any breadcrumb]<p id="breadcrumb">[breadcrumb]</p>[end]
|
||||
<div id="content">
|
||||
<div id="info-box"><h1>[if-any title][title][else][site_name][end]</h1> </div>
|
||||
[prelude]
|
||||
[body]
|
||||
</div>
|
||||
<div id="footer"><p id="lasso">Powered by Lasso</p></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
|
@ -1,26 +0,0 @@
|
|||
This package was debianized by Frederic Peters <dlaniel@entrouvert.com> on
|
||||
Wed, 03 Sep 2008 15:48:49 +0200.
|
||||
|
||||
Upstream Author: Frederic Peters <fpeters@entrouvert.com>
|
||||
|
||||
Copyright (c) 2005 Entr'ouvert;
|
||||
Copyright (c) 2003-2005 dotclear for the graphics.
|
||||
|
||||
License is GNU GPL v2 or later plus OpenSSL exception clause.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License can be found in `/usr/share/common-licenses/GPL'.
|
||||
|
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
2.4
|
|
@ -1,5 +0,0 @@
|
|||
try:
|
||||
from quixote.ptl import compile_package
|
||||
compile_package(__path__)
|
||||
except ImportError:
|
||||
pass
|
|
@ -1,8 +0,0 @@
|
|||
import authentic.admin.root
|
||||
|
||||
class AdminRootDirectory(authentic.admin.root.RootDirectory):
|
||||
menu_items = [
|
||||
('logger/', N_('Logs')),
|
||||
('settings/', N_('Settings')),
|
||||
('debug/', N_('Debug')),
|
||||
('/', N_('Authentic Identity Server'))]
|
|
@ -1,225 +0,0 @@
|
|||
import lasso
|
||||
|
||||
from quixote import get_request, get_response, get_session, redirect
|
||||
from quixote.directory import AccessControlled, Directory
|
||||
from qommon.publisher import get_publisher_class
|
||||
|
||||
from qommon.backoffice.menu import html_top
|
||||
|
||||
from qommon import errors, get_cfg
|
||||
from qommon.form import *
|
||||
|
||||
from authentic import misc
|
||||
|
||||
import identities_ui
|
||||
import services_ui
|
||||
import directory
|
||||
|
||||
class BackofficeRootDirectory(AccessControlled, Directory):
|
||||
_q_exports = ['', 'identities', 'services', 'editcol']
|
||||
items = [
|
||||
('identities/', N_('Identities Management')),
|
||||
('services/', N_('Services Management')),
|
||||
('/', N_('Pr@tic Backoffice'))]
|
||||
|
||||
identities = identities_ui.IdentitiesDirectory()
|
||||
services = services_ui.ServicesDirectory()
|
||||
|
||||
collectivity = None
|
||||
|
||||
def _q_access(self):
|
||||
get_response().breadcrumb.append( ('backoffice/', _('Back Office')) )
|
||||
user = get_session().get_user_object()
|
||||
if not user.is_admin() and not user.is_local_admin():
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
if user.is_admin():
|
||||
# reset directory attributes
|
||||
self.collectivity = None
|
||||
self.identities.collectivity = None
|
||||
self.services.collectivity = None
|
||||
else:
|
||||
self.collectivity = user.get_collectivity()
|
||||
self.identities.collectivity = self.collectivity
|
||||
self.services.collectivity = self.collectivity
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top(_('Back Office'))
|
||||
|
||||
if not self.collectivity:
|
||||
user = get_session().get_user_object()
|
||||
agent = user.get_as_agent()
|
||||
collectivity = directory.get_collectivity(agent.get_collectivity())
|
||||
service_instances = directory.get_service_instances(collectivity)
|
||||
|
||||
if service_instances:
|
||||
providers = get_cfg('providers', {})
|
||||
'<h3>%s</h3>' % _('Services')
|
||||
|
||||
'<ul>'
|
||||
for service in service_instances:
|
||||
service_type = directory.get_service(service.cdg59serviceType)
|
||||
service_label = service_type.cn
|
||||
service_description = service_type.description
|
||||
|
||||
if service_type.cdg59isGlobal:
|
||||
url = service_type.cdg59URL
|
||||
else:
|
||||
url = service.cdg59URL
|
||||
|
||||
metadata_url = service.cdg59metadataURL or service_type.cdg59metadataURL
|
||||
|
||||
if metadata_url:
|
||||
try:
|
||||
klp = [x for x, y in providers.items() if \
|
||||
metadata_url == y.get('metadata_url')] [0]
|
||||
except IndexError:
|
||||
# bad, unregistered saml provider
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
provider, unused_label = misc.get_provider_and_label(klp)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if provider.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0:
|
||||
url = '../saml/sp/%s/login' % klp
|
||||
else:
|
||||
url = '../liberty/sp/%s/login' % klp
|
||||
|
||||
if not url:
|
||||
continue
|
||||
|
||||
if url in (service_type.cdg59URL, service.cdg59URL):
|
||||
label = _('Go to %s') % service_label
|
||||
else:
|
||||
label = _('Log on %s') % service_label
|
||||
|
||||
'<li><a href="%s">%s</a>' % (url, label)
|
||||
'</li>'
|
||||
|
||||
'</ul>'
|
||||
|
||||
'<h3>%s</h3>' % _('Collectivities')
|
||||
|
||||
'<ul class="biglist">'
|
||||
for collectivity in directory.get_sorted_collectivities():
|
||||
'<li class="biglistitem">'
|
||||
'<strong class="label">%s</<strong>' % collectivity.cn
|
||||
'<p class="commands">'
|
||||
if collectivity.ou != 'admin':
|
||||
' <a href="%s/">%s</a> - ' % (collectivity.ou, _('Edit'))
|
||||
' <a href="identities/%s/">%s</a>' % (collectivity.ou, _('Identities'))
|
||||
' - '
|
||||
' <a href="services/%s/">%s</a> ' % (collectivity.ou, _('Services'))
|
||||
'</p>'
|
||||
'</li>'
|
||||
'</ul>'
|
||||
else:
|
||||
'<h3>%s</h3>' % self.collectivity.cn
|
||||
'\n<dl>\n'
|
||||
for k, l, a in self.collectivity.get_attrs():
|
||||
if k == 'cn':
|
||||
continue
|
||||
if getattr(self.collectivity, k):
|
||||
' <dt>%s</dt>' % _(l)
|
||||
' <dd>%s</dd>\n' % getattr(self.collectivity, k)
|
||||
'\n</dl>'
|
||||
|
||||
'<p>'
|
||||
'<a href="editcol">%s</a>' % _('Edit Collectivity')
|
||||
' - '
|
||||
'<a href="identities/">%s</a>' % _('Identities')
|
||||
' - '
|
||||
'<a href="services/">%s</a>' % _('Services')
|
||||
'</p>'
|
||||
|
||||
def _q_lookup(self, component):
|
||||
if not self.collectivity:
|
||||
for collectivity in directory.get_collectivities():
|
||||
if collectivity.ou == component:
|
||||
return CollectivityDirectory(collectivity)
|
||||
raise errors.TraversalError()
|
||||
|
||||
def editcol [html] (self):
|
||||
if not self.collectivity:
|
||||
raise errors.TraversalError()
|
||||
form = Form(enctype='multipart/form-data')
|
||||
for k, l, attrs in self.collectivity.get_attrs():
|
||||
if k in ('cn', 'cdg59collectivityId'):
|
||||
continue
|
||||
form.add(StringWidget, k, title = _(l),
|
||||
value = getattr(self.collectivity, k),
|
||||
**attrs)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top(self.collectivity.cn)
|
||||
'<h2>%s</h2>' % self.collectivity.cn
|
||||
form.render()
|
||||
else:
|
||||
self.submit_col(form)
|
||||
return redirect('..')
|
||||
|
||||
def submit_col(self, form):
|
||||
changed = []
|
||||
for k, l, a in self.collectivity.get_attrs():
|
||||
if k in ('cn', 'cdg59collectivityId'):
|
||||
continue
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
old_v = getattr(self.collectivity, k)
|
||||
if v != old_v:
|
||||
setattr(self.collectivity, k, v)
|
||||
changed.append(k)
|
||||
self.collectivity.save(changed)
|
||||
|
||||
|
||||
|
||||
class CollectivityDirectory(Directory):
|
||||
_q_exports = ['']
|
||||
|
||||
def __init__(self, collectivity):
|
||||
get_response().breadcrumb.append((collectivity.ou + '/', collectivity.cn))
|
||||
self.collectivity = collectivity
|
||||
|
||||
def _q_index [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
for k, l, attrs in self.collectivity.get_attrs():
|
||||
form.add(StringWidget, k, title = _(l),
|
||||
value = getattr(self.collectivity, k),
|
||||
**attrs)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top(self.collectivity.cn)
|
||||
'<h2>%s</h2>' % self.collectivity.cn
|
||||
form.render()
|
||||
else:
|
||||
self.submit(form)
|
||||
return redirect('..')
|
||||
|
||||
def submit(self, form):
|
||||
changed = []
|
||||
for k, l, a in self.collectivity.get_attrs():
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
old_v = getattr(self.collectivity, k)
|
||||
if v != old_v:
|
||||
setattr(self.collectivity, k, v)
|
||||
changed.append(k)
|
||||
self.collectivity.save(changed)
|
||||
|
||||
|
||||
|
||||
get_publisher_class().backoffice_directory_class = BackofficeRootDirectory
|
|
@ -1,634 +0,0 @@
|
|||
import sys
|
||||
from sha import sha
|
||||
import base64
|
||||
import re
|
||||
|
||||
try:
|
||||
import ldap
|
||||
import ldap.async
|
||||
import ldap.modlist
|
||||
import ldap.filter
|
||||
except ImportError:
|
||||
print >> sys.stderr, 'Missing LDAP module'
|
||||
ldap = None
|
||||
|
||||
from qommon import get_publisher
|
||||
from qommon import emails
|
||||
|
||||
from qommon.admin.emails import EmailsDirectory
|
||||
|
||||
def utf8toiso(s):
|
||||
return unicode(s, 'utf-8').encode('iso-8859-1')
|
||||
|
||||
def isotoutf8(s):
|
||||
return unicode(s, 'iso-8859-1').encode('utf-8')
|
||||
|
||||
class UnconfiguredError(Exception):
|
||||
pass
|
||||
|
||||
def get_store():
|
||||
store = get_publisher().store
|
||||
if not hasattr(store, 'pratic_ldap_url'):
|
||||
raise UnconfiguredError()
|
||||
return store
|
||||
|
||||
class Collectivity:
|
||||
dn = None
|
||||
|
||||
ou = None
|
||||
cn = None
|
||||
postalAddress = None
|
||||
telephoneNumber = None
|
||||
facsimileTelephoneNumber = None
|
||||
mail = None
|
||||
cdg59URL = None
|
||||
cdg59collectivityId = None
|
||||
|
||||
ldap_entry = None
|
||||
|
||||
def __init__(self, entry):
|
||||
self.ldap_entry = entry
|
||||
self.dn = entry[0]
|
||||
data = entry[1]
|
||||
for attribute in ('ou', 'cn', 'postalAddress', 'telephoneNumber',
|
||||
'facsimileTelephoneNumber', 'mail', 'cdg59URL',
|
||||
'cdg59collectivityId'):
|
||||
v = data.get(attribute)
|
||||
if v:
|
||||
setattr(self, attribute, utf8toiso(data.get(attribute)[0]))
|
||||
|
||||
def save(self, changed):
|
||||
if not changed:
|
||||
return
|
||||
new_entry = self.ldap_entry[1].copy()
|
||||
for attribute in changed:
|
||||
if attribute in ('cn','postalAddress',):
|
||||
new_entry[attribute] = isotoutf8(getattr(self, attribute))
|
||||
else:
|
||||
new_entry[attribute] = getattr(self, attribute)
|
||||
if not new_entry[attribute]:
|
||||
new_entry[attribute] = []
|
||||
|
||||
mod_list = ldap.modlist.modifyModlist(self.ldap_entry[1], new_entry)
|
||||
store = get_store()
|
||||
store.ldap_conn.modify_s(self.ldap_entry[0], mod_list)
|
||||
|
||||
def delete(self):
|
||||
store = get_store()
|
||||
store.ldap_conn.delete_s(self.ldap_entry[0])
|
||||
|
||||
def get_attrs(self):
|
||||
return [ ('cn', N_('Name'), {'required': True}),
|
||||
('postalAddress', N_('Geopostal Address'), {}),
|
||||
('telephoneNumber', N_('Telephone Number'), {}),
|
||||
('facsimileTelephoneNumber', N_('Fax Number'), {}),
|
||||
('mail', N_('Mail'), {}),
|
||||
('cdg59URL', N_('Website'), {}),
|
||||
('cdg59collectivityId', N_('Collectivity Code'), {})
|
||||
]
|
||||
|
||||
|
||||
def get_collectivities():
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, 'objectClass=cdg59collectivity')
|
||||
return [Collectivity(x) for x in result]
|
||||
|
||||
def get_collectivity(ou):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(ou=%s)(objectclass=cdg59collectivity))', (ou,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return Collectivity(result[0])
|
||||
|
||||
|
||||
|
||||
def get_sorted_collectivities():
|
||||
result = get_collectivities()
|
||||
def cmp_collectivities(x, y):
|
||||
if x.dn == y.dn:
|
||||
return 0
|
||||
if x.ou == 'admin':
|
||||
return 1
|
||||
if y.ou == 'admin':
|
||||
return -1
|
||||
return cmp(x.cn, y.cn)
|
||||
result.sort(cmp_collectivities)
|
||||
return result
|
||||
|
||||
class Agent:
|
||||
uid = None
|
||||
cn = None
|
||||
mail = None
|
||||
cdg59isAdmin = False
|
||||
cdg59isDisabled = False
|
||||
sn = None
|
||||
givenName = None
|
||||
cdg59direction = None
|
||||
ou = None
|
||||
employeeType = None
|
||||
postalAddress = None
|
||||
telephoneNumber = None
|
||||
facsimileTelephoneNumber = None
|
||||
mobile = None
|
||||
cdg59agentSirhCode = None
|
||||
cdg59serviceAccesses = None
|
||||
cdg59lastConnectionTime = None
|
||||
cdg59lastConnectionDuration = None
|
||||
|
||||
ldap_entry = None
|
||||
|
||||
def __init__(self, entry):
|
||||
self.ldap_entry = entry
|
||||
self.dn = entry[0]
|
||||
data = entry[1]
|
||||
for attribute in ('cn', 'mail', 'sn', 'givenName', 'cdg59direction',
|
||||
'ou', 'employeeType', 'postalAddress', 'telephoneNumber',
|
||||
'facsimileTelephoneNumber', 'mobile', 'cdg59isAdmin',
|
||||
'cdg59isDisabled', 'cdg59agentSirhCode'):
|
||||
v = data.get(attribute)
|
||||
if v:
|
||||
setattr(self, attribute, utf8toiso(data.get(attribute)[0]))
|
||||
|
||||
self.cdg59isAdmin = (self.cdg59isAdmin == 'TRUE')
|
||||
self.cdg59isDisabled = (self.cdg59isDisabled == 'TRUE')
|
||||
if data.get('cdg59serviceAccesses'):
|
||||
self.cdg59serviceAccesses = [utf8toiso(x) for x in data.get('cdg59serviceAccesses')]
|
||||
else:
|
||||
self.cdg59serviceAccesses = []
|
||||
|
||||
if data.get('cdg59lastConnectionTime'):
|
||||
self.cdg59lastConnectionTime = int(data.get('cdg59lastConnectionTime')[0])
|
||||
if data.get('cdg59lastConnectionDuration'):
|
||||
self.cdg59lastConnectionDuration = int(data.get('cdg59lastConnectionDuration')[0])
|
||||
|
||||
self.username = data.get('uid')[0]
|
||||
|
||||
def save(self, changed):
|
||||
if not changed:
|
||||
return
|
||||
new_entry = self.ldap_entry[1].copy()
|
||||
for attribute in changed:
|
||||
new_entry[attribute] = getattr(self, attribute)
|
||||
if type(new_entry[attribute]) is int:
|
||||
new_entry[attribute] = [str(new_entry[attribute])]
|
||||
if type(new_entry[attribute]) is str:
|
||||
new_entry[attribute] = isotoutf8(new_entry[attribute])
|
||||
if new_entry[attribute] is None:
|
||||
new_entry[attribute] = []
|
||||
|
||||
if 'cdg59agentSirhCode' in changed:
|
||||
# check for an existing agent with such SIRH code
|
||||
try:
|
||||
get_agent_by_sirh(self.cdg59agentSirhCode)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
raise ldap.ALREADY_EXISTS('cdg59agentSirhCode')
|
||||
|
||||
if 'mail' in changed:
|
||||
# check for an existing agent with such mail
|
||||
try:
|
||||
get_agent_by_email(self.mail)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
raise ldap.ALREADY_EXISTS('mail')
|
||||
|
||||
if 'cdg59isAdmin' in changed:
|
||||
if self.cdg59isAdmin:
|
||||
new_entry['cdg59isAdmin'] = 'TRUE'
|
||||
else:
|
||||
new_entry['cdg59isAdmin'] = ''
|
||||
|
||||
if 'cdg59isDisabled' in changed:
|
||||
if self.cdg59isDisabled:
|
||||
new_entry['cdg59isDisabled'] = 'TRUE'
|
||||
else:
|
||||
new_entry['cdg59isDisabled'] = ''
|
||||
|
||||
if 'sn' in changed or 'givenName' in changed:
|
||||
# change common name too
|
||||
new_entry['cn'] = '%s %s' % (self.givenName, self.sn)
|
||||
new_entry['cn'] = isotoutf8(new_entry['cn'])
|
||||
|
||||
mod_list = ldap.modlist.modifyModlist(self.ldap_entry[1], new_entry)
|
||||
store = get_store()
|
||||
store.ldap_conn.modify_s(self.ldap_entry[0], mod_list)
|
||||
|
||||
def change_password(self, password):
|
||||
userPassword = ['{sha}%s' % base64.encodestring(sha(password).digest()).strip()]
|
||||
mod_list = [(ldap.MOD_REPLACE, 'userPassword', userPassword)]
|
||||
store = get_store()
|
||||
store.ldap_conn.modify_s(self.ldap_entry[0], mod_list)
|
||||
|
||||
def delete(self):
|
||||
store = get_store()
|
||||
store.ldap_conn.delete_s(self.ldap_entry[0])
|
||||
|
||||
_collectivity = None
|
||||
def get_collectivity(self):
|
||||
if self._collectivity:
|
||||
return self._collectivity
|
||||
self._collectivity = self.dn.split(',')[1].split('=')[1]
|
||||
return self._collectivity
|
||||
|
||||
def get_admin_agents(self):
|
||||
'''Get this agent "superiors"'''
|
||||
store = get_store()
|
||||
|
||||
if self.cdg59isAdmin:
|
||||
request_str = '(objectclass=cdg59agent)'
|
||||
base_dn = 'ou=admin,' + store.pratic_ldap_base
|
||||
else:
|
||||
request_str = '(&(cdg59isAdmin=TRUE)(objectclass=cdg59agent))'
|
||||
base_dn = 'ou=%s,%s' % (self.get_collectivity(), store.pratic_ldap_base)
|
||||
|
||||
result = store.ldap_conn.search_s(base_dn, ldap.SCOPE_SUBTREE, request_str)
|
||||
agents = [Agent(x) for x in result]
|
||||
return agents
|
||||
|
||||
def notify_access_changes(self):
|
||||
if not self.mail:
|
||||
return
|
||||
all_services = get_services()
|
||||
services = []
|
||||
for service in all_services:
|
||||
if service.cdg59sid in self.cdg59serviceAccesses:
|
||||
services.append(service.cn)
|
||||
services.sort()
|
||||
|
||||
services = ' - ' + '\n - '.join(services)
|
||||
|
||||
data = {
|
||||
'agent': self.cn,
|
||||
'services': services,
|
||||
}
|
||||
emails.custom_ezt_email('pratic-agent-access-changes', data,
|
||||
[self.mail], fire_and_forget = True)
|
||||
|
||||
def notify_enabled(self):
|
||||
if not self.mail:
|
||||
return
|
||||
data = { 'agent': self.cn }
|
||||
emails.custom_ezt_email('pratic-agent-enabled', data,
|
||||
[self.mail], fire_and_forget = True)
|
||||
|
||||
def notify_disabled(self):
|
||||
if not self.mail:
|
||||
return
|
||||
data = { 'agent': self.cn }
|
||||
emails.custom_ezt_email('pratic-agent-disabled', data,
|
||||
[self.mail], fire_and_forget = True)
|
||||
|
||||
|
||||
def search_agents(collectivity, search, sorted = False):
|
||||
store = get_store()
|
||||
|
||||
request_str = ldap.filter.filter_format('(&(|(sn=%s*)(cn=%s*)(cdg59agentSirhCode=%s))(objectclass=cdg59agent))',
|
||||
(search, search, search))
|
||||
if collectivity:
|
||||
base_dn = collectivity.dn
|
||||
else:
|
||||
store = get_store()
|
||||
base_dn = store.pratic_ldap_base
|
||||
|
||||
result = store.ldap_conn.search_s(base_dn, ldap.SCOPE_SUBTREE, request_str)
|
||||
agents = [Agent(x) for x in result]
|
||||
if sorted:
|
||||
agents.sort(lambda x,y: cmp(x.sn.lower(), y.sn.lower()))
|
||||
return agents
|
||||
|
||||
|
||||
def get_agents(collectivity, first_letter = None, sorted = False):
|
||||
store = get_store()
|
||||
if first_letter:
|
||||
request_str = ldap.filter.filter_format('(&(sn=%s*)(objectclass=cdg59agent))', (first_letter,))
|
||||
else:
|
||||
request_str = 'objectClass=cdg59agent'
|
||||
result = store.ldap_conn.search_s(collectivity.dn, ldap.SCOPE_SUBTREE, request_str)
|
||||
agents = [Agent(x) for x in result]
|
||||
if sorted:
|
||||
agents.sort(lambda x,y: cmp(x.sn.lower(), y.sn.lower()))
|
||||
return agents
|
||||
|
||||
|
||||
|
||||
def get_agent(collectivity, username):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(collectivity.dn,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(uid=%s)(objectclass=cdg59agent))', (username,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return Agent(result[0])
|
||||
|
||||
|
||||
def get_agent_by_sirh(sirh):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(cdg59agentSirhCode=%s)(objectclass=cdg59agent))', (sirh,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return Agent(result[0])
|
||||
|
||||
|
||||
def get_agent_by_email(email):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(mail=%s)(objectclass=cdg59agent))', (email,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return Agent(result[0])
|
||||
|
||||
|
||||
def get_collectivity_name(collectivity):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(ou=%s)(objectClass=cdg59collectivity))', (collectivity,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return utf8toiso(result[0][1].get('cn')[0])
|
||||
|
||||
|
||||
def add_agent(collectivity, data):
|
||||
uid = data.get('uid')
|
||||
dn = 'uid=%s, %s' % (data.get('uid'), collectivity.dn)
|
||||
password = None
|
||||
if data.get('password'):
|
||||
password = data.get('password')
|
||||
del data['password']
|
||||
data['cn'] = '%s %s' % (data['givenName'], data['sn'])
|
||||
for k in data:
|
||||
data[k] = [isotoutf8(data[k])]
|
||||
data['objectClass'] = 'cdg59agent'
|
||||
if data.get('cdg59agentSirhCode'):
|
||||
# check for an existing agent with such SIRH code
|
||||
try:
|
||||
get_agent_by_sirh(data.get('cdg59agentSirhCode')[0])
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
raise ldap.ALREADY_EXISTS('cdg59agentSirhCode')
|
||||
if data.get('mail'):
|
||||
# check for an existing agent with such SIRH code
|
||||
try:
|
||||
get_agent_by_email(data.get('mail')[0])
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
raise ldap.ALREADY_EXISTS('mail')
|
||||
store = get_store()
|
||||
mod_list = ldap.modlist.addModlist(data)
|
||||
store.ldap_conn.add_s(dn, mod_list)
|
||||
|
||||
if password:
|
||||
agent = get_agent(collectivity, uid)
|
||||
agent.change_password(password)
|
||||
|
||||
|
||||
def add_service(data):
|
||||
store = get_store()
|
||||
dn = 'cdg59sid=%s,%s' % (data.get('cdg59sid'), store.pratic_ldap_base)
|
||||
for k in data:
|
||||
if k == 'cdg59isGlobal':
|
||||
if data[k]:
|
||||
data['cdg59isGlobal'] = 'TRUE'
|
||||
else:
|
||||
data['cdg59isGlobal'] = 'FALSE'
|
||||
else:
|
||||
data[k] = [isotoutf8(data[k])]
|
||||
data['objectClass'] = 'cdg59service'
|
||||
mod_list = ldap.modlist.addModlist(data)
|
||||
store.ldap_conn.add_s(dn, mod_list)
|
||||
|
||||
|
||||
class ServiceInstance:
|
||||
dn = None
|
||||
cdg59siid = None
|
||||
cdg59URL = None
|
||||
cdg59metadataURL = None
|
||||
cdg59serviceType = None
|
||||
|
||||
ldap_entry = None
|
||||
|
||||
def __init__(self, entry = None):
|
||||
if not entry:
|
||||
return
|
||||
self.ldap_entry = entry
|
||||
self.dn = entry[0]
|
||||
data = entry[1]
|
||||
for attribute in ('cdg59siid', 'cdg59URL', 'cdg59metadataURL', 'cdg59serviceType'):
|
||||
v = data.get(attribute)
|
||||
if v:
|
||||
setattr(self, attribute, utf8toiso(data.get(attribute)[0]))
|
||||
|
||||
def save(self, changed):
|
||||
if not changed:
|
||||
return
|
||||
new_entry = self.ldap_entry[1].copy()
|
||||
for attribute in changed:
|
||||
new_entry[attribute] = getattr(self, attribute)
|
||||
if not new_entry[attribute]:
|
||||
new_entry[attribute] = []
|
||||
|
||||
mod_list = ldap.modlist.modifyModlist(self.ldap_entry[1], new_entry)
|
||||
store = get_store()
|
||||
store.ldap_conn.modify_s(self.ldap_entry[0], mod_list)
|
||||
|
||||
_name = None
|
||||
def get_name(self):
|
||||
if self._name:
|
||||
return self._name
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(cdg59sid=%s)(objectClass=cdg59service))', (self.cdg59siid,)))
|
||||
try:
|
||||
self._name = utf8toiso(result[0][1]['cn'][0])
|
||||
except IndexError:
|
||||
self._name = '%s (e)' % self.cdg59siid
|
||||
return self._name
|
||||
name = property(get_name)
|
||||
|
||||
def delete(self):
|
||||
store = get_store()
|
||||
store.ldap_conn.delete_s(self.ldap_entry[0])
|
||||
|
||||
def add(self, collectivity):
|
||||
data = {}
|
||||
dn = 'cdg59siid=%s, %s' % (self.cdg59siid, collectivity.dn)
|
||||
data['objectClass'] = 'cdg59serviceInstance'
|
||||
data['cdg59siid'] = self.cdg59siid
|
||||
data['cdg59serviceType'] = self.cdg59serviceType
|
||||
if self.cdg59URL:
|
||||
data['cdg59URL'] = self.cdg59URL
|
||||
if self.cdg59metadataURL:
|
||||
data['cdg59metadataURL'] = self.cdg59metadataURL
|
||||
mod_list = ldap.modlist.addModlist(data)
|
||||
store = get_store()
|
||||
store.ldap_conn.add_s(dn, mod_list)
|
||||
|
||||
|
||||
|
||||
def get_service_instances(collectivity):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(collectivity.dn,
|
||||
ldap.SCOPE_SUBTREE, 'objectClass=cdg59serviceInstance')
|
||||
service_instances = [ServiceInstance(x) for x in result]
|
||||
# fill missing fields for global services
|
||||
services = get_services()
|
||||
for si in service_instances:
|
||||
try:
|
||||
s = get_service(si.cdg59serviceType)
|
||||
if s and s.cdg59isGlobal:
|
||||
si.cdg59metadataURL = s.cdg59metadataURL
|
||||
si.cdg59URL = s.cdg59URL
|
||||
except KeyError:
|
||||
# ignore error for removed service type
|
||||
continue
|
||||
return service_instances
|
||||
|
||||
|
||||
|
||||
def get_service_instances_by_service_type(sid):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(objectClass=cdg59serviceInstance)(cdg59serviceType=%s))', (sid,)))
|
||||
service_instances = [ServiceInstance(x) for x in result]
|
||||
# fill missing fields for global services
|
||||
services = get_services()
|
||||
for si in service_instances:
|
||||
try:
|
||||
s = get_service(si.cdg59serviceType)
|
||||
if s and s.cdg59isGlobal:
|
||||
si.cdg59metadataURL = s.cdg59metadataURL
|
||||
si.cdg59URL = s.cdg59URL
|
||||
except KeyError:
|
||||
# ignore error for removed service type
|
||||
continue
|
||||
return service_instances
|
||||
|
||||
|
||||
|
||||
def get_service_instance(collectivity, siid):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(collectivity.dn,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(cdg59siid=%s)(objectclass=cdg59serviceInstance))', (siid,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
si = ServiceInstance(result[0])
|
||||
# fix missing field values for global services
|
||||
try:
|
||||
s = get_service(si.cdg59serviceType)
|
||||
if s and s.cdg59isGlobal:
|
||||
si.cdg59metadataURL = s.cdg59metadataURL
|
||||
si.cdg59URL = s.cdg59URL
|
||||
except KeyError:
|
||||
# ignore error for removed service type
|
||||
pass
|
||||
return si
|
||||
|
||||
|
||||
|
||||
|
||||
class Service:
|
||||
dn = None
|
||||
cn = None
|
||||
cdg59sid = None
|
||||
description = None
|
||||
cdg59isGlobal = False
|
||||
cdg59URL = None
|
||||
cdg59metadataURL = None
|
||||
|
||||
ldap_entry = None
|
||||
|
||||
def __init__(self, entry):
|
||||
self.ldap_entry = entry
|
||||
self.dn = entry[0]
|
||||
data = entry[1]
|
||||
for attribute in ('cn', 'cdg59sid', 'description', 'cdg59isGlobal', 'cdg59URL',
|
||||
'cdg59metadataURL'):
|
||||
v = data.get(attribute)
|
||||
if v:
|
||||
setattr(self, attribute, utf8toiso(data.get(attribute)[0]))
|
||||
|
||||
self.cdg59isGlobal = (self.cdg59isGlobal == 'TRUE')
|
||||
|
||||
def delete(self):
|
||||
store = get_store()
|
||||
store.ldap_conn.delete_s(self.ldap_entry[0])
|
||||
|
||||
def save(self, changed):
|
||||
if not changed:
|
||||
return
|
||||
mod_list = []
|
||||
for attribute in changed:
|
||||
value = getattr(self, attribute)
|
||||
if value:
|
||||
if attribute == 'cdg59isGlobal':
|
||||
if value:
|
||||
value = 'TRUE'
|
||||
else:
|
||||
value = 'FALSE'
|
||||
else:
|
||||
value = isotoutf8(value)
|
||||
if value:
|
||||
mod_list.append((ldap.MOD_REPLACE, attribute, value))
|
||||
else:
|
||||
mod_list.append((ldap.MOD_DELETE, attribute, None))
|
||||
|
||||
store = get_store()
|
||||
store.ldap_conn.modify_s(self.ldap_entry[0], mod_list)
|
||||
|
||||
|
||||
|
||||
def get_service(sid):
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, ldap.filter.filter_format('(&(cdg59sid=%s)(objectclass=cdg59service))', (sid,)))
|
||||
if not result:
|
||||
raise KeyError()
|
||||
return Service(result[0])
|
||||
|
||||
|
||||
|
||||
def get_services():
|
||||
store = get_store()
|
||||
result = store.ldap_conn.search_s(store.pratic_ldap_base,
|
||||
ldap.SCOPE_SUBTREE, 'objectClass=cdg59service')
|
||||
return [Service(x) for x in result]
|
||||
|
||||
|
||||
EmailsDirectory.register('pratic-agent-access-changes',
|
||||
N_('Pr@tic Agent Access Changes'),
|
||||
N_('Available variables: agent, services'),
|
||||
default_subject = N_('Change of access'),
|
||||
default_body = N_('''\
|
||||
Hello [agent],
|
||||
|
||||
There were changes to your service authorizations, you may now access
|
||||
the followind services:
|
||||
|
||||
[services]
|
||||
'''))
|
||||
|
||||
EmailsDirectory.register('pratic-agent-enabled',
|
||||
N_('Pr@tic Agent Enabled'),
|
||||
N_('Available variables: agent'),
|
||||
default_subject = N_('Pr@tic Account Enabled'),
|
||||
default_body = N_('''\
|
||||
Hello [agent],
|
||||
|
||||
Your Pr@tic account has been enabled.
|
||||
'''))
|
||||
|
||||
EmailsDirectory.register('pratic-agent-disabled',
|
||||
N_('Pr@tic Agent Disabled'),
|
||||
N_('Available variables: agent'),
|
||||
default_subject = N_('Pr@tic Account Disabled'),
|
||||
default_body = N_('''\
|
||||
Hello [agent],
|
||||
|
||||
Your Pr@tic account has been disabled.
|
||||
'''))
|
||||
|
|
@ -1,621 +0,0 @@
|
|||
import ldap
|
||||
import re
|
||||
|
||||
from quixote import get_request, get_response, get_session, redirect
|
||||
from quixote.directory import Directory
|
||||
|
||||
from qommon.backoffice.menu import html_top
|
||||
from qommon.admin.menu import command_icon
|
||||
|
||||
from qommon import errors, get_cfg
|
||||
from qommon.form import *
|
||||
|
||||
import string
|
||||
import directory
|
||||
|
||||
def generate_password():
|
||||
passwords_cfg = get_cfg('passwords', {})
|
||||
min_len = passwords_cfg.get('min_length', 0)
|
||||
max_len = passwords_cfg.get('max_length', 0)
|
||||
if min_len == 0 and max_len == 0:
|
||||
password_len = 6
|
||||
elif min_len == 0:
|
||||
password_len = min(6, max_len)
|
||||
elif max_len == 0:
|
||||
password_len = max(6, min_len)
|
||||
else:
|
||||
password_len = (max_len + min_len) / 2
|
||||
return ''.join([random.choice(string.letters) for x in range(password_len)])
|
||||
|
||||
|
||||
class AgentDirectory(Directory):
|
||||
_q_exports = ['', 'edit', 'delete', 'disable', 'enable', 'password']
|
||||
|
||||
attrs = [
|
||||
('cdg59agentSirhCode', N_('SIRH Code'), {'required': True, 'size': 30}),
|
||||
('sn', N_('Last Name'), {'required': True, 'size': 30}),
|
||||
('givenName', N_('First Name'), {'required': True, 'size': 30}),
|
||||
('cdg59direction', N_('Direction'), {'size': 30}),
|
||||
('ou', N_('Service'), {'size': 30}),
|
||||
('employeeType', N_('Functions'), {'size': 30}),
|
||||
('postalAddress', N_('Geopostal Address'), {'size': 30}),
|
||||
('mail', N_('Mail'), {'size': 30, 'required': True}),
|
||||
('telephoneNumber', N_('Telephone Number'), {'size': 30}),
|
||||
('facsimileTelephoneNumber', N_('Fax Number'), {'size': 30}),
|
||||
('mobile', N_('Professional Mobile Number'), {'size': 30}),
|
||||
('cdg59isAdmin', N_('Collectivity Admin'), {'widget_class': CheckboxWidget}),
|
||||
]
|
||||
|
||||
def __init__(self, agent):
|
||||
self.agent = agent
|
||||
get_response().breadcrumb.append((self.agent.username + '/', self.agent.cn))
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top('identities', title = _('Agent: %s') % self.agent.cn)
|
||||
'<h2>%s</h2>' % _('Agent: %s') % self.agent.cn
|
||||
|
||||
if self.agent.cdg59isDisabled:
|
||||
'<p>'
|
||||
_('This account is disabled.')
|
||||
'</p>'
|
||||
|
||||
'\n<dl>\n'
|
||||
'<dt>%s</dt>' % _('Username')
|
||||
'<dd>%s</dd>\n' % self.agent.username
|
||||
|
||||
for k, l, attrs in self.attrs:
|
||||
if getattr(self.agent, k):
|
||||
' <dt>%s</dt>' % _(l)
|
||||
' <dd>%s</dd>\n' % getattr(self.agent,k)
|
||||
'\n</dl>'
|
||||
|
||||
'<p>'
|
||||
'<a href="edit">%s</a> - ' % _('Edit')
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin() or user.is_local_admin():
|
||||
if self.agent.cdg59isDisabled:
|
||||
'<a href="enable">%s</a> - ' % _('Enable Account')
|
||||
else:
|
||||
'<a href="disable">%s</a> - ' % _('Disable Account')
|
||||
if user.is_admin():
|
||||
'<a href="delete" rel="popup">%s</a> - ' % _('Delete')
|
||||
'<a href="password">%s</a>' % _('Change Password')
|
||||
'</p>'
|
||||
|
||||
def edit [html] (self):
|
||||
user = get_session().get_user_object()
|
||||
form = Form(enctype='multipart/form-data')
|
||||
for k, l, attrs in self.attrs:
|
||||
if not user.is_admin() and k in ('cdg59agentSirhCode', 'sn', 'givenName'):
|
||||
continue
|
||||
if attrs.has_key('widget_class'):
|
||||
widget_class = attrs.get('widget_class')
|
||||
attrs = attrs.copy()
|
||||
del attrs['widget_class']
|
||||
else:
|
||||
widget_class = StringWidget
|
||||
form.add(widget_class, k, title = _(l),
|
||||
value = getattr(self.agent, k),
|
||||
**attrs)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
if self.submit(form):
|
||||
return redirect('..')
|
||||
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top('identities', title = _('Agent: %s') % self.agent.cn)
|
||||
'<h2>%s</h2>' % self.agent.cn
|
||||
form.render()
|
||||
|
||||
def submit(self, form):
|
||||
changed = []
|
||||
for k, l, attrs in self.attrs:
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
old_v = getattr(self.agent, k)
|
||||
if v != old_v:
|
||||
setattr(self.agent, k, v)
|
||||
changed.append(k)
|
||||
try:
|
||||
self.agent.save(changed)
|
||||
except ldap.ALREADY_EXISTS, error:
|
||||
if type(error.args[0]) is dict: # native ldap exception
|
||||
form.set_error('uid', _('This username is already in use.'))
|
||||
elif error.args[0] == 'cdg59agentSirhCode':
|
||||
form.set_error('cdg59agentSirhCode', _('This SIRH code is already in use.'))
|
||||
elif error.args[0] == 'mail':
|
||||
form.set_error('mail', _('This email is already in use.'))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def disable(self):
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin() or user.is_local_admin():
|
||||
self.agent.cdg59isDisabled = True
|
||||
self.agent.save(['cdg59isDisabled'])
|
||||
self.agent.notify_disabled()
|
||||
return redirect('.')
|
||||
else:
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
def enable(self):
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin() or user.is_local_admin():
|
||||
self.agent.cdg59isDisabled = False
|
||||
self.agent.save(['cdg59isDisabled'])
|
||||
self.agent.notify_enabled()
|
||||
return redirect('.')
|
||||
else:
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
def delete [html] (self):
|
||||
user = get_session().get_user_object()
|
||||
if not user.is_admin():
|
||||
raise errors.AccessForbiddenError()
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % _(
|
||||
'You are about to irrevocably delete this agent.')))
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('delete', _('Delete')))
|
||||
html_top('identities', title = _('Delete Agent'))
|
||||
'<h2>%s</h2>' % _('Deleting Agent: %s') % self.agent.cn
|
||||
form.render()
|
||||
else:
|
||||
self.agent.delete()
|
||||
return redirect('..')
|
||||
|
||||
def password [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(PasswordWidget, 'new_password', title=_('New Password'), required=True)
|
||||
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('.')
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('password', _('Change Password')))
|
||||
html_top('identities', title = _('Agent: %s') % self.agent.cn)
|
||||
'<h2>%s</h2>' % self.agent.cn
|
||||
form.render()
|
||||
else:
|
||||
self.agent.change_password(str(form.get_widget('new_password').parse()))
|
||||
return redirect('..')
|
||||
|
||||
|
||||
class IdentitiesDirectory(Directory):
|
||||
_q_exports = ['', 'new', 'lookup_sirh', 'authorizations', 'csv']
|
||||
|
||||
collectivity = None
|
||||
|
||||
def __init__(self, collectivity = None):
|
||||
Directory.__init__(self)
|
||||
self.collectivity = collectivity
|
||||
|
||||
def _q_traverse(self, path):
|
||||
user = get_session().get_user_object()
|
||||
if not self.collectivity:
|
||||
get_response().breadcrumb.append(('identities/', _('Identity Management')))
|
||||
if not user.is_admin():
|
||||
self.collectivity = user.get_collectivity()
|
||||
else:
|
||||
if not user.is_admin():
|
||||
get_response().breadcrumb.append(('identities/', _('Identity Management')))
|
||||
return Directory._q_traverse(self, path)
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top('identities', _('Identity Management'))
|
||||
|
||||
get_session().display_message()
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin() and not self.collectivity:
|
||||
# list all collectivities
|
||||
|
||||
form = Form()
|
||||
form.add(StringWidget, 'search', title = _('Search'))
|
||||
form.render()
|
||||
|
||||
if form.is_submitted():
|
||||
return self.all_search_results(form.get_widget('search').parse())
|
||||
|
||||
'<ul>'
|
||||
for collectivity in directory.get_sorted_collectivities():
|
||||
'<li><a href="%s/">' % collectivity.ou
|
||||
collectivity.cn
|
||||
'</a></li>'
|
||||
'</ul>'
|
||||
else:
|
||||
'<h2>'
|
||||
self.collectivity.cn
|
||||
'</h2>'
|
||||
|
||||
'<p>'
|
||||
if user.is_admin():
|
||||
'<a href="../../services/%s/">%s</a> - ' % (
|
||||
self.collectivity.ou, _('Services Management'))
|
||||
else:
|
||||
'<a href="../services/">%s</a> - ' % _('Services Management')
|
||||
if user.is_admin():
|
||||
'<a href="new">%s</a> - ' % _('Add a new Agent')
|
||||
'<a href="csv">%s</a> - ' % _('Import CSV File')
|
||||
if (user.is_admin() or user.is_local_admin()) and (self.collectivity.ou != 'admin'):
|
||||
'<a href="authorizations">%s</a>' % _('Manage Authorizations')
|
||||
'</p>'
|
||||
|
||||
|
||||
form = Form()
|
||||
form.add(StringWidget, 'search', title = _('Search'))
|
||||
form.render()
|
||||
|
||||
if form.is_submitted():
|
||||
agents = directory.search_agents(self.collectivity,
|
||||
form.get_widget('search').parse(), sorted = True)
|
||||
else:
|
||||
current_letter = get_request().form.get('letter', 'A')
|
||||
if str(current_letter) not in list(string.letters) + ['all']:
|
||||
current_letter = 'A'
|
||||
'<div class="letters-nav">'
|
||||
for letter in string.uppercase:
|
||||
if letter == current_letter:
|
||||
'<span class="current-letter">%s</span>' % letter
|
||||
else:
|
||||
'<a href="?letter=%s">%s</a>' % (letter, letter)
|
||||
'-'
|
||||
if letter == string.uppercase[-1]:
|
||||
letter = N_('all')
|
||||
if letter == current_letter:
|
||||
'<span class="current-letter">(%s)</span>' % _(letter)
|
||||
else:
|
||||
'<a href="?letter=%s">(%s)</a>' % (letter, _(letter))
|
||||
'</div>'
|
||||
|
||||
if current_letter == 'all':
|
||||
agents = directory.get_agents(self.collectivity, sorted = True)
|
||||
else:
|
||||
agents = directory.get_agents(self.collectivity,
|
||||
first_letter = current_letter, sorted = True)
|
||||
|
||||
'<ul class="biglist">'
|
||||
for agent in agents:
|
||||
if agent.cdg59isDisabled:
|
||||
'<li class="biglistitem disabled">'
|
||||
elif agent.cdg59isAdmin:
|
||||
'<li class="biglistitem admin">'
|
||||
else:
|
||||
'<li class="biglistitem">'
|
||||
'<strong class="label">%s</strong>' % agent.cn
|
||||
'<p class="commands">'
|
||||
command_icon('%s/' % agent.username, 'view')
|
||||
command_icon('%s/edit' % agent.username, 'edit')
|
||||
if user.is_admin():
|
||||
command_icon('%s/delete' % agent.username, 'remove', popup = True)
|
||||
'</p></li>'
|
||||
'</ul>'
|
||||
|
||||
if user.is_admin():
|
||||
'<p>'
|
||||
'<a href="../">%s</a>' % _('Back')
|
||||
'</p>'
|
||||
|
||||
def all_search_results [html] (self, query):
|
||||
agents = directory.search_agents(None, query, sorted = True)
|
||||
user = get_session().get_user_object()
|
||||
|
||||
agents.sort(lambda x,y: cmp(x.get_collectivity(), y.get_collectivity()))
|
||||
|
||||
last_col = None
|
||||
|
||||
for agent in agents:
|
||||
agent_col = agent.get_collectivity()
|
||||
if agent_col != last_col:
|
||||
if last_col is not None:
|
||||
'</ul>'
|
||||
try:
|
||||
'<h2>%s</h2>' % directory.get_collectivity_name(agent_col)
|
||||
except KeyError:
|
||||
'<h2>%s</h2>' % _('Unknown Collectivity')
|
||||
'<ul class="biglist">'
|
||||
last_col = agent_col
|
||||
|
||||
if agent.cdg59isDisabled:
|
||||
'<li class="biglistitem disabled">'
|
||||
elif agent.cdg59isAdmin:
|
||||
'<li class="biglistitem admin">'
|
||||
else:
|
||||
'<li class="biglistitem">'
|
||||
'<strong class="label">%s</strong>' % agent.cn
|
||||
'<p class="commands">'
|
||||
command_icon('%s/%s/' % (agent_col, agent.username), 'view')
|
||||
command_icon('%s/%s/edit' % (agent_col, agent.username), 'edit')
|
||||
if user.is_admin():
|
||||
command_icon('%s/%s/delete' % (agent_col, agent.username),
|
||||
'remove', popup = True)
|
||||
'</p></li>'
|
||||
|
||||
if last_col is not None:
|
||||
'</ul>'
|
||||
|
||||
def authorizations [html] (self):
|
||||
if not self.collectivity:
|
||||
raise errors.TraversalError()
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if not (user.is_admin() or user.is_local_admin()):
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
if get_request().get_method() == 'POST':
|
||||
return self.authorizations_submit()
|
||||
|
||||
html_top('identities', _('Authorizations Management'))
|
||||
get_response().breadcrumb.append(('authorizations', _('Authorizations Management')))
|
||||
|
||||
get_session().display_message()
|
||||
|
||||
services = directory.get_service_instances(self.collectivity)
|
||||
|
||||
current_letter = get_request().form.get('letter', 'A')
|
||||
if str(current_letter) not in list(string.letters) + ['all']:
|
||||
current_letter = 'A'
|
||||
'<div class="letters-nav">'
|
||||
for letter in string.uppercase:
|
||||
if letter == current_letter:
|
||||
'<span class="current-letter">%s</span>' % letter
|
||||
else:
|
||||
'<a href="?letter=%s">%s</a>' % (letter, letter)
|
||||
'-'
|
||||
if letter == string.uppercase[-1]:
|
||||
letter = N_('all')
|
||||
if letter == current_letter:
|
||||
'<span class="current-letter">(%s)</span>' % _(letter)
|
||||
else:
|
||||
'<a href="?letter=%s">(%s)</a>' % (letter, _(letter))
|
||||
'</div>'
|
||||
|
||||
if current_letter == 'all':
|
||||
agents = directory.get_agents(self.collectivity, sorted = True)
|
||||
else:
|
||||
agents = directory.get_agents(self.collectivity,
|
||||
first_letter = current_letter, sorted = True)
|
||||
|
||||
'<form method="post">'
|
||||
'<input type="hidden" name="letter" value="%s"/>' % current_letter
|
||||
'<table>'
|
||||
'<thead>'
|
||||
'<tr>'
|
||||
'<td></td>'
|
||||
saml_services = []
|
||||
for service in services:
|
||||
if service.cdg59metadataURL:
|
||||
saml_services.append(service)
|
||||
else:
|
||||
service_type = directory.get_service(service.cdg59serviceType)
|
||||
if service_type.cdg59metadataURL:
|
||||
saml_services.append(service)
|
||||
else:
|
||||
continue
|
||||
'<th>%s</th>' % service.name
|
||||
'</tr>'
|
||||
'</thead>'
|
||||
'<tbody>'
|
||||
for agent in agents:
|
||||
if agent.cdg59isDisabled:
|
||||
'<tr class="disabled">'
|
||||
else:
|
||||
'<tr>'
|
||||
'<th>%s</th>' % agent.cn
|
||||
for service in saml_services:
|
||||
'<td>'
|
||||
'<input name="%s" type="checkbox" value="%s"' % (agent.username, service.cdg59siid)
|
||||
if service.cdg59siid in agent.cdg59serviceAccesses:
|
||||
' checked="checked"'
|
||||
'/>'
|
||||
'</td>'
|
||||
'</tr>'
|
||||
'</tbody>'
|
||||
'</table>'
|
||||
|
||||
'<input type="submit" value="%s"/>' % _('Submit')
|
||||
'</form>'
|
||||
|
||||
def authorizations_submit(self):
|
||||
current_letter = get_request().form.get('letter', 'A')
|
||||
if current_letter == 'all':
|
||||
agents = directory.get_agents(self.collectivity, sorted = True)
|
||||
else:
|
||||
agents = directory.get_agents(self.collectivity,
|
||||
first_letter = current_letter, sorted = True)
|
||||
|
||||
form = get_request().form
|
||||
for agent in agents:
|
||||
accesses = agent.cdg59serviceAccesses
|
||||
new_value = form.get(agent.username, [])
|
||||
if sorted(accesses) != sorted(new_value):
|
||||
agent.cdg59serviceAccesses = new_value
|
||||
agent.save(changed = ['cdg59serviceAccesses'])
|
||||
agent.notify_access_changes()
|
||||
get_session().message = ('info', _('New authorizations saved succesfully.'))
|
||||
return redirect('authorizations?letter=%s' % current_letter)
|
||||
|
||||
def lookup_sirh(self):
|
||||
form = Form(action = 'lookup_sirh')
|
||||
form.add(StringWidget, 'sirh', title = _('Search on SIRH Code'), size = 10,
|
||||
required = True)
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_session().message = ('error', _('Error looking up agent'))
|
||||
return redirect('.')
|
||||
|
||||
sirh = form.get_widget('sirh').parse()
|
||||
try:
|
||||
agent = directory.get_agent_by_sirh(sirh)
|
||||
except KeyError:
|
||||
get_session().message = ('error', _('No agent found with this SIRH'))
|
||||
return redirect('.')
|
||||
|
||||
uid, collectivity, foobar = agent.dn.split(',', 2)
|
||||
uid = uid.split('=')[1]
|
||||
collectivity = collectivity.split('=')[1]
|
||||
|
||||
if self.collectivity:
|
||||
return redirect('../%s/%s/' % (collectivity, uid))
|
||||
else:
|
||||
return redirect('%s/%s/' % (collectivity, uid))
|
||||
|
||||
|
||||
def new [html] (self):
|
||||
user = get_session().get_user_object()
|
||||
if not user.is_admin():
|
||||
raise errors.AccessForbiddenError()
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(StringWidget, 'uid', title = _('Pr@tic Username'), required = True, size = 30)
|
||||
form.add(StringWidget, 'cdg59agentSirhCode', title = _('SIRH Code'), required = True,
|
||||
size = 30)
|
||||
form.add(StringWidget, 'sn', title = _('Last Name'), required = True, size = 30)
|
||||
form.add(StringWidget, 'givenName', title = _('First Name'), required = True, size = 30)
|
||||
form.add(StringWidget, 'mail', title = _('Mail'), size = 30, required = True)
|
||||
|
||||
form.add(StringWidget, 'password', title = _('Password'), size = 30, required = True,
|
||||
value = generate_password())
|
||||
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('.')
|
||||
|
||||
if form.is_submitted():
|
||||
uid = form.get_widget('uid').parse()
|
||||
if uid and not re.match(str('^[A-Za-z0-9\.-]+$'), uid):
|
||||
form.set_error('uid', _('wrong format'))
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
agent = self.submit_new(form)
|
||||
if agent:
|
||||
return self.newly_created_agent(form, agent)
|
||||
|
||||
get_response().breadcrumb.append(('new', _('New')))
|
||||
html_top('identities', title = _('New Agent'))
|
||||
'<h2>%s</h2>' % _('New Agent')
|
||||
form.render()
|
||||
|
||||
|
||||
def newly_created_agent [html] (self, form, agent):
|
||||
get_response().breadcrumb.append(('new', _('New')))
|
||||
html_top('identities', title = _('New Agent'))
|
||||
|
||||
'<h2>%s</h2>' % _('New Agent')
|
||||
|
||||
'<p>'
|
||||
_('A new agent has been created in the LDAP directory, you may want to send '
|
||||
'those login informations :')
|
||||
'</p>'
|
||||
'<ul>'
|
||||
'<li>%s</li>' % _('Username: %s') % agent.username
|
||||
'<li>%s</li>' % _('Password: %s') % form.get_widget('password').parse()
|
||||
'</ul>'
|
||||
|
||||
'<p>'
|
||||
'<a href="new">%s</a>' % _('Add another agent')
|
||||
' - '
|
||||
'<a href="%s/edit">%s</a>' % (agent.username, _('Edit other fields'))
|
||||
'</p>'
|
||||
|
||||
|
||||
def submit_new(self, form):
|
||||
try:
|
||||
directory.add_agent(self.collectivity, {
|
||||
'uid': form.get_widget('uid').parse(),
|
||||
'sn': form.get_widget('sn').parse(),
|
||||
'givenName': form.get_widget('givenName').parse(),
|
||||
'cdg59agentSirhCode': form.get_widget('cdg59agentSirhCode').parse(),
|
||||
'password': form.get_widget('password').parse(),
|
||||
'mail': form.get_widget('mail').parse()})
|
||||
except ldap.ALREADY_EXISTS, error:
|
||||
if type(error.args[0]) is dict: # native ldap exception
|
||||
form.set_error('uid', _('This username is already in use.'))
|
||||
elif error.args[0] == 'cdg59agentSirhCode':
|
||||
form.set_error('cdg59agentSirhCode', _('This SIRH code is already in use.'))
|
||||
elif error.args[0] == 'mail':
|
||||
form.set_error('mail', _('This email is already in use.'))
|
||||
return None
|
||||
|
||||
return directory.get_agent(self.collectivity, form.get_widget('uid').parse())
|
||||
|
||||
def csv [html] (self):
|
||||
user = get_session().get_user_object()
|
||||
if not user.is_admin():
|
||||
raise errors.AccessForbiddenError()
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(FileWidget, 'csv', title = _('CSV File'), required = True)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('.')
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('csv', _('CSV Import')))
|
||||
html_top('identities', title = _('CSV Import'))
|
||||
'<h2>%s</h2>' % _('CSV Import')
|
||||
'<p>'
|
||||
_('Fields must be separated by ; and in the following order.')
|
||||
'</p>'
|
||||
'<p>'
|
||||
_('You will get a CSV file with generated identifies and passwords appended.')
|
||||
'</p>'
|
||||
'<ul>'
|
||||
for i, attr in enumerate(AgentDirectory.attrs):
|
||||
'<li>%s</li>' % _(attr[1])
|
||||
'</ul>'
|
||||
form.render()
|
||||
else:
|
||||
return self.csv_submit(form)
|
||||
|
||||
def csv_submit(self, form):
|
||||
output = []
|
||||
for line in form.get_widget('csv').parse().fp.readlines():
|
||||
fields = line.strip().split(';')
|
||||
data = {}
|
||||
for i, attr in enumerate(AgentDirectory.attrs):
|
||||
if fields[i]:
|
||||
data[attr[0]] = fields[i]
|
||||
data['uid'] = ('%s.%s' % (data['givenName'], data['sn'])).lower()
|
||||
data['password'] = generate_password()
|
||||
output.append(line.strip() + ';%s;%s' % (data['uid'], data['password']))
|
||||
try:
|
||||
directory.add_agent(self.collectivity, data)
|
||||
except:
|
||||
output[-1] = output[-1] + ';ERROR'
|
||||
|
||||
response = get_response()
|
||||
response.set_content_type('text/csv')
|
||||
response.set_header('content-disposition', 'attachment; filename=result.csv')
|
||||
return '\n'.join(output)
|
||||
|
||||
def _q_lookup(self, component):
|
||||
if not self.collectivity:
|
||||
for collectivity in directory.get_collectivities():
|
||||
if collectivity.ou == component:
|
||||
get_response().breadcrumb.append((component + '/', collectivity.cn))
|
||||
return IdentitiesDirectory(collectivity)
|
||||
else:
|
||||
# lookup for agent
|
||||
try:
|
||||
agent = directory.get_agent(self.collectivity, component)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
return AgentDirectory(agent)
|
||||
raise errors.TraversalError()
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
import lasso
|
||||
import Cookie
|
||||
|
||||
from quixote import redirect, get_session
|
||||
from qommon import get_cfg, get_logger
|
||||
from qommon.form import *
|
||||
from qommon import template
|
||||
import authentic.root
|
||||
|
||||
from qommon.admin.texts import TextsDirectory
|
||||
from qommon.admin.emails import EmailsDirectory
|
||||
from qommon import emails
|
||||
from qommon import errors
|
||||
|
||||
|
||||
from authentic import identities
|
||||
from authentic import misc
|
||||
|
||||
import directory
|
||||
import store
|
||||
import admin
|
||||
|
||||
OldRootDirectory = authentic.root.RootDirectory
|
||||
|
||||
from saml2 import AlternateSaml2Directory
|
||||
|
||||
from identities_ui import AgentDirectory
|
||||
|
||||
|
||||
|
||||
class AlternateRootDirectory(OldRootDirectory):
|
||||
backoffice = None
|
||||
admin = admin.AdminRootDirectory()
|
||||
|
||||
saml = AlternateSaml2Directory()
|
||||
|
||||
def __init__(self):
|
||||
OldRootDirectory.__init__(self)
|
||||
self._q_exports = OldRootDirectory._q_exports + [
|
||||
'backoffice', 'profile', 'issue', 'password']
|
||||
|
||||
def _q_index [html] (self):
|
||||
session = get_session()
|
||||
if not session or not session.user:
|
||||
return self.login()
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin():
|
||||
return redirect('/backoffice/')
|
||||
|
||||
agent = user.get_as_agent()
|
||||
template.html_top(_('Welcome, %s') % agent.cn)
|
||||
|
||||
if hasattr(session, str('previousConnectionTime')):
|
||||
'<p>'
|
||||
_('Last session started: %s') % misc.localstrftime(
|
||||
time.localtime(session.previousConnectionTime))
|
||||
if session.previousConnectionDuration:
|
||||
_(' (duration: %dm)') % int(session.previousConnectionDuration/60)
|
||||
'</p>'
|
||||
|
||||
all_services = directory.get_services()
|
||||
|
||||
collectivity = directory.get_collectivity(agent.get_collectivity())
|
||||
service_instances = directory.get_service_instances(collectivity)
|
||||
|
||||
providers = get_cfg('providers', {})
|
||||
accesses = user.get_as_agent().cdg59serviceAccesses or []
|
||||
'<ul id="services">'
|
||||
for service in service_instances:
|
||||
try:
|
||||
service_type = directory.get_service(service.cdg59serviceType)
|
||||
except KeyError:
|
||||
# ignore service type that has been removed globally
|
||||
continue
|
||||
service_label = service_type.cn
|
||||
service_description = service_type.description
|
||||
|
||||
if service_type.cdg59isGlobal:
|
||||
url = service_type.cdg59URL
|
||||
else:
|
||||
url = service.cdg59URL
|
||||
|
||||
metadata_url = service.cdg59metadataURL or service_type.cdg59metadataURL
|
||||
|
||||
if not service.cdg59siid in accesses and metadata_url:
|
||||
# only skip access to liberty/saml services
|
||||
continue
|
||||
|
||||
if metadata_url:
|
||||
try:
|
||||
klp = [x for x, y in providers.items() if \
|
||||
metadata_url == y.get('metadata_url')] [0]
|
||||
except IndexError:
|
||||
# bad, unregistered saml provider
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
provider, unused_label = misc.get_provider_and_label(klp)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if provider.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0:
|
||||
url = 'saml/sp/%s/login' % klp
|
||||
else:
|
||||
url = 'liberty/sp/%s/login' % klp
|
||||
|
||||
if not url:
|
||||
continue
|
||||
|
||||
if url in (service_type.cdg59URL, service.cdg59URL):
|
||||
label = _('Go to %s') % service_label
|
||||
else:
|
||||
label = _('Log on %s') % service_label
|
||||
|
||||
'<li><a href="%s">%s</a>' % (url, label)
|
||||
if service_description:
|
||||
' <p class="service_description">%s</p>' % service_description
|
||||
'</li>'
|
||||
|
||||
'</ul>'
|
||||
|
||||
t = TextsDirectory.get_html_text('pratic-platform-status')
|
||||
if t:
|
||||
'<div id="platform-status">'
|
||||
'<h3>%s</h3>' % _('Platform Status')
|
||||
'<div>'
|
||||
htmltext(t)
|
||||
'</div>'
|
||||
if not user.is_admin():
|
||||
'<p id="report-issue">'
|
||||
'<a href="/issue">%s</a>' % _('Report an issue')
|
||||
'</p>'
|
||||
'</div>'
|
||||
|
||||
|
||||
'<p id="commands">'
|
||||
'<a href="/profile">%s</a> - ' % _('View Profile')
|
||||
|
||||
passwords_cfg = get_cfg('passwords', {})
|
||||
if passwords_cfg.get('can_change', False):
|
||||
'<a href="/password">%s</a> - ' % _('Change Password')
|
||||
if user.is_admin():
|
||||
'<a href="/admin/">%s</a> - ' % _('Administration Interface')
|
||||
'<a href="/backoffice/">%s</a> - ' % _('Back Office Interface')
|
||||
'<a href="/singleLogout">%s</a>' % _('Logout')
|
||||
elif user.is_local_admin():
|
||||
'<a href="/backoffice/">%s</a> - ' % _('Back Office Interface')
|
||||
'<a href="/singleLogout">%s</a>' % _('Logout')
|
||||
else:
|
||||
'<a href="/singleLogout">%s</a>' % _('Logout')
|
||||
'</p>'
|
||||
|
||||
def _q_traverse(self, path):
|
||||
get_publisher().store = identities.load_store()
|
||||
|
||||
try:
|
||||
store = directory.get_store()
|
||||
except directory.UnconfiguredError:
|
||||
if path and path[0] not in ['admin', 'qo', 'css', 'themes', 'js']:
|
||||
return template.error_page(_('Directory must first be configured'))
|
||||
|
||||
if not self.backoffice:
|
||||
self.backoffice = get_publisher().backoffice_directory_class()
|
||||
session = get_session()
|
||||
if session:
|
||||
identities.get_store().connect(session)
|
||||
return OldRootDirectory._q_traverse(self, path)
|
||||
|
||||
def get_login_form(self):
|
||||
form = OldRootDirectory.get_login_form(self)
|
||||
try:
|
||||
collectivities = directory.get_sorted_collectivities()
|
||||
except directory.UnconfiguredError:
|
||||
return form
|
||||
collectivities = [(x.dn, x.cn) for x in collectivities]
|
||||
password_widget = form.widgets[-1]
|
||||
form.widgets.remove(password_widget)
|
||||
try:
|
||||
collectivity = get_request().cookies['collectivity']
|
||||
except KeyError:
|
||||
collectivity = None
|
||||
if collectivity not in [x[0] for x in collectivities]:
|
||||
collectivity = None
|
||||
form.add(SingleSelectWidget, 'collectivity', title = _('Collectivity'), required = True,
|
||||
value = collectivity, options = collectivities)
|
||||
form.widgets.append(password_widget)
|
||||
return form
|
||||
|
||||
def login_submit(self, form):
|
||||
try:
|
||||
store = directory.get_store()
|
||||
except directory.UnconfiguredError:
|
||||
return OldRootDirectory.login_submit(self, form)
|
||||
|
||||
username = form.get_widget('username').parse()
|
||||
password = form.get_widget('password').parse()
|
||||
collectivity = form.get_widget('collectivity').parse()
|
||||
|
||||
identity = store.get_identity_for_account(username, password, collectivity)
|
||||
if identity is None:
|
||||
get_logger().warn('Authentication Failure (un: %s)' % username)
|
||||
raise authentic.root.LoginError()
|
||||
|
||||
session = get_session()
|
||||
session.set_user(identity.id)
|
||||
get_request().user = identity.id
|
||||
store.init_session(session, password)
|
||||
identity.register_new_session()
|
||||
|
||||
get_response().set_cookie('collectivity', collectivity, path = '/',
|
||||
expires = Cookie._getdate(90*86400))
|
||||
|
||||
return self.login_success(identity)
|
||||
|
||||
def forgot_password(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def profile [html] (self):
|
||||
if not get_request().user:
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
get_response().breadcrumb.append(('profile', _('Your Profile')))
|
||||
template.html_top(_('Your Profile'))
|
||||
|
||||
user = get_session().get_user_object()
|
||||
agent = user.get_as_agent()
|
||||
|
||||
'<dl class="profile">'
|
||||
for k, l, attrs in AgentDirectory.attrs:
|
||||
if k in ('cdg59isAdmin',):
|
||||
continue
|
||||
if attrs.has_key('widget_class'):
|
||||
widget_class = attrs.get('widget_class')
|
||||
attrs = attrs.copy()
|
||||
del attrs['widget_class']
|
||||
else:
|
||||
widget_class = StringWidget
|
||||
'<dt>%s</dt>' % _(l)
|
||||
if getattr(agent, k):
|
||||
'<dd>%s</dd>' % getattr(agent, k)
|
||||
else:
|
||||
'<dd>-</dd>'
|
||||
'</dl>'
|
||||
|
||||
'<p>'
|
||||
'<a href=".">%s</a>' % _('Home')
|
||||
|
||||
def password [html] (self):
|
||||
passwords_cfg = get_cfg('passwords', {})
|
||||
if not passwords_cfg.get('can_change', False):
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
if not get_request().user:
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
form = Form(enctype='multipart/form-data')
|
||||
|
||||
form.add(PasswordWidget, 'new_password', title=_('New Password'), required=True)
|
||||
form.add(PasswordWidget, 'new2_password', title=_('New Password (confirmation)'),
|
||||
required=True)
|
||||
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('.')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
new_password = form.get_widget('new_password').parse()
|
||||
new2_password = form.get_widget('new2_password').parse()
|
||||
|
||||
if new_password != new2_password:
|
||||
form.set_error('new2_password', _('Passwords do not match'))
|
||||
else:
|
||||
min_length = int(passwords_cfg.get('min_length', 0))
|
||||
if len(new_password) < min_length:
|
||||
form.set_error('new_password',
|
||||
_('Password is too short. It must be at least %d characters.') % min_length)
|
||||
max_length = int(passwords_cfg.get('max_length', 0))
|
||||
if max_length and len(new_password) > max_length:
|
||||
form.set_error('new_password',
|
||||
_('Password is too long. It must be at most %d characters.') % max_length)
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('password', _('Change Password')))
|
||||
template.html_top(_('Change Password'))
|
||||
form.render()
|
||||
else:
|
||||
user = get_session().get_user_object()
|
||||
agent = user.get_as_agent()
|
||||
|
||||
agent.change_password(str(form.get_widget('new_password').parse()))
|
||||
return redirect('..')
|
||||
|
||||
def issue [html] (self):
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin():
|
||||
return template.error_page(_('You are not one to report issues.'))
|
||||
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(TextWidget, 'description', title = _('Description'), cols = 60, rows = 10)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('.')
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('issue', _('Issue Report')))
|
||||
template.html_top(_('Reporting an Issue'))
|
||||
'<p>'
|
||||
if user.is_local_admin():
|
||||
_('The issue will be sent to Pr@tic administrators.')
|
||||
else:
|
||||
_('The issue will be sent to your local administrators.')
|
||||
'</p>'
|
||||
form.render()
|
||||
else:
|
||||
self.issue_submit(form)
|
||||
return redirect('.')
|
||||
|
||||
def issue_submit(self, form):
|
||||
user = get_session().get_user_object()
|
||||
agent = user.get_as_agent()
|
||||
description = form.get_widget('description').parse()
|
||||
|
||||
admins = agent.get_admin_agents()
|
||||
admin_emails = [x.mail for x in admins if x.mail]
|
||||
|
||||
data = {
|
||||
'agent': agent.cn,
|
||||
'description': description,
|
||||
}
|
||||
emails.custom_ezt_email('pratic-issue-report', data, admin_emails, fire_and_forget = True)
|
||||
|
||||
from qommon.publisher import get_publisher_class
|
||||
get_publisher_class().root_directory_class = AlternateRootDirectory
|
||||
|
||||
TextsDirectory.register('pratic-platform-status', N_('Pr@tic Platform Status'))
|
||||
|
||||
|
||||
EmailsDirectory.register('pratic-issue-report',
|
||||
N_('Pr@tic Issue Report'),
|
||||
N_('Available variables: agent, description'),
|
||||
default_subject = N_('Pr@tic Issue'),
|
||||
default_body = N_('''\
|
||||
Agent [agent] reported the following problem:
|
||||
|
||||
[description]
|
||||
'''))
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
from quixote import get_session
|
||||
|
||||
from qommon import get_cfg
|
||||
from qommon import errors
|
||||
from qommon import template
|
||||
|
||||
import liberty.saml2
|
||||
|
||||
import misc
|
||||
|
||||
import directory
|
||||
|
||||
def check_access_authorizations(provider_key):
|
||||
session = get_session()
|
||||
if not session or session.user is None:
|
||||
return False
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin():
|
||||
return True
|
||||
|
||||
collectivity = user.get_collectivity()
|
||||
service_instances = directory.get_service_instances(collectivity)
|
||||
|
||||
providers = get_cfg('providers', {})
|
||||
accesses = user.get_as_agent().cdg59serviceAccesses or []
|
||||
|
||||
for service in service_instances:
|
||||
try:
|
||||
service_type = directory.get_service(service.cdg59serviceType)
|
||||
except KeyError:
|
||||
# ignore service type removed globally
|
||||
continue
|
||||
|
||||
if not service.cdg59siid in accesses:
|
||||
continue
|
||||
|
||||
# handle global services
|
||||
if service_type.cdg59isGlobal:
|
||||
cdg59metadataURL = service_type.cdg59metadataURL
|
||||
else:
|
||||
cdg59metadataURL = service.cdg59metadataURL
|
||||
|
||||
if not cdg59metadataURL:
|
||||
continue
|
||||
|
||||
try:
|
||||
klp = [x for x, y in providers.items() if \
|
||||
cdg59metadataURL == y.get('metadata_url')] [0]
|
||||
except IndexError:
|
||||
continue
|
||||
|
||||
if provider_key == klp:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AccessControlSpUI(liberty.saml2.SpUI):
|
||||
def _q_access(self):
|
||||
authorized = check_access_authorizations(self.provider_key)
|
||||
if not authorized:
|
||||
if get_session():
|
||||
raise errors.AccessForbiddenError()
|
||||
else:
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
def login(self, encryption_mode = None, method = None, nid_format = None, relay_state = None):
|
||||
return liberty.saml2.SpUI.login(self, encryption_mode, method, nid_format, 'backoffice')
|
||||
|
||||
|
||||
class AccessControlSpDir(liberty.saml2.SpDir):
|
||||
def _q_lookup(self, component):
|
||||
return AccessControlSpUI(component)
|
||||
|
||||
|
||||
class AlternateSaml2Directory(liberty.saml2.RootDirectory):
|
||||
sp = AccessControlSpDir()
|
||||
|
||||
def check_access_authorizations(self, login):
|
||||
provider_id = login.remoteProviderId
|
||||
provider_key = misc.get_provider_key(provider_id)
|
||||
return check_access_authorizations(provider_key)
|
||||
|
||||
def sso_after_authentication(self, login, user_authenticated, proxied = False):
|
||||
if user_authenticated:
|
||||
if not self.check_access_authorizations(login):
|
||||
provider_id = login.remoteProviderId
|
||||
provider_key = misc.get_provider_key(provider_id)
|
||||
try:
|
||||
label = misc.get_provider_and_label(provider_key)[1]
|
||||
except KeyError:
|
||||
return template.error_page(_('''\
|
||||
You do not have required authorizations to access the service,
|
||||
you should contact the administration of your collectivity.'''))
|
||||
|
||||
return template.error_page(_('''\
|
||||
You do not have required authorizations to access the "%s" service,
|
||||
you should contact the administration of your collectivity.''') % label)
|
||||
return liberty.saml2.RootDirectory.sso_after_authentication(
|
||||
self, login, user_authenticated, proxied=proxied)
|
|
@ -1,600 +0,0 @@
|
|||
import lasso
|
||||
import tempfile
|
||||
import re
|
||||
import urllib2
|
||||
import ldap.dn
|
||||
import ldap
|
||||
|
||||
from quixote import get_request, get_response, get_session, redirect, get_publisher
|
||||
from quixote.directory import Directory
|
||||
from quixote.html import htmltext, htmlescape, url_quote
|
||||
|
||||
from qommon.backoffice.menu import html_top
|
||||
from qommon.admin.menu import command_icon
|
||||
|
||||
from qommon import errors
|
||||
from qommon import misc
|
||||
from qommon.form import *
|
||||
from qommon import template
|
||||
|
||||
import directory
|
||||
|
||||
class ServiceInstanceDirectory(Directory):
|
||||
_q_exports = ['', 'edit', 'delete', 'update']
|
||||
|
||||
attrs = [
|
||||
('cdg59URL', _('URL to service root'),
|
||||
{'widget_class': ValidUrlWidget, 'size': 80}),
|
||||
('cdg59metadataURL', _('URL to service metadata'),
|
||||
{'widget_class': ValidUrlWidget, 'size': 80}),
|
||||
]
|
||||
|
||||
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
try:
|
||||
self.service_type = directory.get_service(self.service.cdg59serviceType)
|
||||
except KeyError:
|
||||
raise
|
||||
get_response().breadcrumb.append((self.service.cdg59siid + '/', self.service.name))
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top('services', title = _('Service: %s') % self.service.name)
|
||||
'<h2>%s</h2>' % _('Service: %s') % self.service.name
|
||||
|
||||
get_session().display_message()
|
||||
|
||||
'<p>'
|
||||
if not self.service_type.cdg59isGlobal:
|
||||
'<a href="edit">%s</a> - ' % _('Edit')
|
||||
'<a href="delete" rel="popup">%s</a>' % _('Unsubscribe')
|
||||
if self.service.cdg59metadataURL:
|
||||
' - <a href="update">%s</a>' % _('Update SAML Metadata')
|
||||
'</p>'
|
||||
|
||||
def edit [html] (self):
|
||||
if self.service_type.cdg59isGlobal:
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top('services', title = _('Service: %s') % self.service.name)
|
||||
'<p>'
|
||||
_('Global Service, nothing to do here')
|
||||
'</p>'
|
||||
'<p><a href=".">%s</a></p>' % _('Back')
|
||||
else:
|
||||
form = Form(enctype='multipart/form-data')
|
||||
|
||||
for k, l, attrs in self.attrs:
|
||||
if not attrs:
|
||||
attrs = {}
|
||||
if attrs.has_key('widget_class'):
|
||||
widget_class = attrs.get('widget_class')
|
||||
attrs = attrs.copy()
|
||||
del attrs['widget_class']
|
||||
else:
|
||||
widget_class = StringWidget
|
||||
form.add(widget_class, k, title = _(l),
|
||||
value = getattr(self.service, k),
|
||||
**attrs)
|
||||
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
self.submit(form)
|
||||
if not form.has_errors():
|
||||
return redirect('..')
|
||||
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top('services', title = _('Service: %s') % self.service.name)
|
||||
'<h2>%s</h2>' % self.service.name
|
||||
form.render()
|
||||
|
||||
def submit(self, form):
|
||||
old_metadata_url = self.service.cdg59metadataURL
|
||||
changed = []
|
||||
for k, l, attrs in self.attrs:
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
old_v = getattr(self.service, k)
|
||||
if v != old_v:
|
||||
setattr(self.service, k, v)
|
||||
changed.append(k)
|
||||
|
||||
if 'cdg59metadataURL' in changed:
|
||||
if not self.service.cdg59metadataURL:
|
||||
d = get_cfg('providers', {})
|
||||
for k in d.keys():
|
||||
if d[k].get('metadata_url') == old_metadata_url:
|
||||
del d[k]
|
||||
get_publisher().write_cfg()
|
||||
break
|
||||
else:
|
||||
try:
|
||||
rfd = urllib2.urlopen(self.service.cdg59metadataURL)
|
||||
except:
|
||||
raise
|
||||
form.set_error('cdg59metadataURL', _('Failed to retrieve file'))
|
||||
return
|
||||
|
||||
s = rfd.read()
|
||||
(bfd, metadata_pathname) = tempfile.mkstemp('.metadata')
|
||||
open(metadata_pathname, 'w').write(s)
|
||||
try:
|
||||
p = lasso.Provider(lasso.PROVIDER_ROLE_SP, metadata_pathname, None, None)
|
||||
except lasso.Error:
|
||||
form.set_error('cdg59metadataURL',
|
||||
_('Failed to create Lasso provider with those metadata'))
|
||||
return
|
||||
|
||||
key_provider_id = misc.get_provider_key(p.providerId)
|
||||
|
||||
dir = get_publisher().app_dir
|
||||
metadata_fn = 'provider-%s-metadata.xml' % key_provider_id
|
||||
|
||||
d = get_cfg('providers', {})
|
||||
get_publisher().cfg['providers'] = d
|
||||
|
||||
d[key_provider_id] = {}
|
||||
d[key_provider_id]['role'] = lasso.PROVIDER_ROLE_SP
|
||||
d[key_provider_id]['metadata'] = metadata_fn
|
||||
d[key_provider_id]['metadata_url'] = self.service.cdg59metadataURL
|
||||
file(misc.get_abs_path(metadata_fn), 'w').write(s)
|
||||
get_publisher().write_cfg()
|
||||
|
||||
self.service.save(changed)
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
rfd = urllib2.urlopen(self.service.cdg59metadataURL)
|
||||
except:
|
||||
get_session().message = ('error', _('Failed to load metadata'))
|
||||
return redirect('.')
|
||||
|
||||
s = rfd.read()
|
||||
(bfd, metadata_pathname) = tempfile.mkstemp('.metadata')
|
||||
open(metadata_pathname, 'w').write(s)
|
||||
try:
|
||||
p = lasso.Provider(lasso.PROVIDER_ROLE_SP, metadata_pathname, None, None)
|
||||
except lasso.Error:
|
||||
get_session().message = ('error',
|
||||
_('Failed to create Lasso provider with those metadata'))
|
||||
return redirect('.')
|
||||
|
||||
key_provider_id = misc.get_provider_key(p.providerId)
|
||||
|
||||
dir = get_publisher().app_dir
|
||||
metadata_fn = 'provider-%s-metadata.xml' % key_provider_id
|
||||
|
||||
d = get_cfg('providers', {})
|
||||
get_publisher().cfg['providers'] = d
|
||||
|
||||
d[key_provider_id] = {}
|
||||
d[key_provider_id]['role'] = lasso.PROVIDER_ROLE_SP
|
||||
d[key_provider_id]['metadata'] = metadata_fn
|
||||
d[key_provider_id]['metadata_url'] = self.service.cdg59metadataURL
|
||||
file(misc.get_abs_path(metadata_fn), 'w').write(s)
|
||||
get_publisher().write_cfg()
|
||||
|
||||
get_session().message = ('info', _('Metadata have been successfully updated.'))
|
||||
|
||||
return redirect('.')
|
||||
|
||||
def delete [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % _(
|
||||
'You are about to unsubscribe the collectivity from this service.')))
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('..')
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('delete', _('Delete')))
|
||||
html_top('services', title = _('Unsubscribing from Service'))
|
||||
'<h2>%s</h2>' % _('Unsubscring from Service: %s') % self.service.name
|
||||
form.render()
|
||||
else:
|
||||
self.service.delete()
|
||||
# XXX: remove lasso provider if it exists
|
||||
return redirect('..')
|
||||
|
||||
|
||||
|
||||
class ServiceDirectory(Directory):
|
||||
_q_exports = ['', 'edit', 'delete', 'update']
|
||||
|
||||
attrs = [
|
||||
('cn', _('Name'), {'required': True}),
|
||||
('description', _('Description'), {'widget_class': TextWidget, 'cols': 60, 'rows': 5}),
|
||||
('cdg59URL', _('URL to service root'),
|
||||
{'widget_class': ValidUrlWidget, 'size': 80}),
|
||||
('cdg59metadataURL', _('URL to service metadata'),
|
||||
{'widget_class': ValidUrlWidget, 'size': 80}),
|
||||
('cdg59isGlobal', _('Global Service'), {'widget_class': CheckboxWidget}),
|
||||
]
|
||||
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top('services', title = _('Service: %s') % self.service.cn)
|
||||
|
||||
'<h2>%s</h2>' % self.service.cn
|
||||
|
||||
get_session().display_message()
|
||||
|
||||
'<p>'
|
||||
self.service.description
|
||||
'</p>'
|
||||
|
||||
'<p>'
|
||||
'<a href="edit">%s</a> - ' % _('Edit')
|
||||
'<a href="delete" rel="popup">%s</a>' % _('Delete')
|
||||
if self.service.cdg59metadataURL:
|
||||
' - <a href="update">%s</a>' % _('Update SAML Metadata')
|
||||
'</p>'
|
||||
|
||||
def edit [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
for k, l, attrs in self.attrs:
|
||||
if not attrs:
|
||||
attrs = {}
|
||||
if attrs.has_key('widget_class'):
|
||||
widget_class = attrs.get('widget_class')
|
||||
attrs = attrs.copy()
|
||||
del attrs['widget_class']
|
||||
else:
|
||||
widget_class = StringWidget
|
||||
form.add(widget_class, k, title = _(l),
|
||||
value = getattr(self.service, k),
|
||||
**attrs)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('../..')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
self.submit(form)
|
||||
if not form.has_errors():
|
||||
return redirect('..')
|
||||
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top('services', title = _('Service: %s') % self.service.cn)
|
||||
'<h2>%s</h2>' % self.service.cn
|
||||
form.render()
|
||||
|
||||
|
||||
def submit(self, form):
|
||||
changed = []
|
||||
old_metadata_url = self.service.cdg59metadataURL
|
||||
for k, l, attrs in self.attrs:
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
old_v = getattr(self.service, k)
|
||||
if v != old_v:
|
||||
setattr(self.service, k, v)
|
||||
changed.append(k)
|
||||
|
||||
if 'cdg59metadataURL' in changed:
|
||||
if not self.service.cdg59metadataURL:
|
||||
d = get_cfg('providers', {})
|
||||
for k in d.keys():
|
||||
if d[k].get('metadata_url') == old_metadata_url:
|
||||
del d[k]
|
||||
get_publisher().write_cfg()
|
||||
break
|
||||
else:
|
||||
try:
|
||||
rfd = urllib2.urlopen(self.service.cdg59metadataURL)
|
||||
except:
|
||||
form.set_error('cdg59metadataURL', _('Failed to retrieve file'))
|
||||
return
|
||||
|
||||
s = rfd.read()
|
||||
(bfd, metadata_pathname) = tempfile.mkstemp('.metadata')
|
||||
open(metadata_pathname, 'w').write(s)
|
||||
try:
|
||||
p = lasso.Provider(lasso.PROVIDER_ROLE_SP, metadata_pathname, None, None)
|
||||
except lasso.Error:
|
||||
form.set_error('cdg59metadataURL',
|
||||
_('Failed to create Lasso provider with those metadata'))
|
||||
return
|
||||
|
||||
key_provider_id = misc.get_provider_key(p.providerId)
|
||||
|
||||
dir = get_publisher().app_dir
|
||||
metadata_fn = 'provider-%s-metadata.xml' % key_provider_id
|
||||
|
||||
d = get_cfg('providers', {})
|
||||
get_publisher().cfg['providers'] = d
|
||||
|
||||
d[key_provider_id] = {}
|
||||
d[key_provider_id]['role'] = lasso.PROVIDER_ROLE_SP
|
||||
d[key_provider_id]['metadata'] = metadata_fn
|
||||
d[key_provider_id]['metadata_url'] = self.service.cdg59metadataURL
|
||||
file(misc.get_abs_path(metadata_fn), 'w').write(s)
|
||||
get_publisher().write_cfg()
|
||||
|
||||
self.service.save(changed)
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
rfd = urllib2.urlopen(self.service.cdg59metadataURL)
|
||||
except:
|
||||
get_session().message = ('error', _('Failed to load metadata'))
|
||||
return redirect('.')
|
||||
|
||||
s = rfd.read()
|
||||
(bfd, metadata_pathname) = tempfile.mkstemp('.metadata')
|
||||
open(metadata_pathname, 'w').write(s)
|
||||
try:
|
||||
p = lasso.Provider(lasso.PROVIDER_ROLE_SP, metadata_pathname, None, None)
|
||||
except lasso.Error:
|
||||
get_session().message = ('error',
|
||||
_('Failed to create Lasso provider with those metadata'))
|
||||
return redirect('.')
|
||||
|
||||
key_provider_id = misc.get_provider_key(p.providerId)
|
||||
|
||||
dir = get_publisher().app_dir
|
||||
metadata_fn = 'provider-%s-metadata.xml' % key_provider_id
|
||||
|
||||
d = get_cfg('providers', {})
|
||||
get_publisher().cfg['providers'] = d
|
||||
|
||||
d[key_provider_id] = {}
|
||||
d[key_provider_id]['role'] = lasso.PROVIDER_ROLE_SP
|
||||
d[key_provider_id]['metadata'] = metadata_fn
|
||||
d[key_provider_id]['metadata_url'] = self.service.cdg59metadataURL
|
||||
file(misc.get_abs_path(metadata_fn), 'w').write(s)
|
||||
get_publisher().write_cfg()
|
||||
|
||||
get_session().message = ('info', _('Metadata have been successfully updated.'))
|
||||
|
||||
return redirect('.')
|
||||
|
||||
def delete [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % _(
|
||||
'You are about to irrevocably delete this service.')))
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('../..')
|
||||
service_instances = directory.get_service_instances_by_service_type(self.service.cdg59sid)
|
||||
if service_instances:
|
||||
error_text = htmltext('<p>%s :</p>' % _('Cannot delete service. There are still service instances for this service'))
|
||||
error_text += htmltext('<ul>')
|
||||
for si in service_instances:
|
||||
sid=si.cdg59siid
|
||||
try:
|
||||
ou=[x[0][1] for x in ldap.dn.str2dn(si.dn, flags=ldap.DN_FORMAT_LDAPV3) if x[0][0] == 'ou' ][0]
|
||||
collectivity = directory.get_collectivity(ou)
|
||||
ou = collectivity.ou
|
||||
link = url_quote("../../%s/%s/delete" % (ou,sid))
|
||||
error_text += htmltext('<li> %s - %s <a href="%s" target="_delete_%s">%s</a></li>' % (collectivity.cn, si.name, link, ou, _('Delete')))
|
||||
except KeyError:
|
||||
error_text += htmltext('<li>%s</li>' % htmlescape(si.dn))
|
||||
|
||||
error_text += htmltext('</ul>')
|
||||
get_session().message = ('error', error_text)
|
||||
|
||||
if not form.is_submitted() or form.has_errors() or service_instances:
|
||||
get_response().breadcrumb.append(('delete', _('Delete')))
|
||||
html_top('services', title = _('Delete Service'))
|
||||
get_session().display_message()
|
||||
'<h2>%s</h2>' % _('Deleting Service: %s') % self.service.cn
|
||||
form.render()
|
||||
else:
|
||||
self.service.delete()
|
||||
return redirect('../..')
|
||||
|
||||
|
||||
class ServiceLookupDirectory(Directory):
|
||||
_q_exports = ['', 'new']
|
||||
|
||||
def _q_index(self):
|
||||
return redirect('..')
|
||||
|
||||
def new [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(StringWidget, 'cdg59sid', title = _('Service Identifier'), required = True,
|
||||
hint = _('All lowercase, no space or special characters'))
|
||||
for k, l, attrs in ServiceDirectory.attrs:
|
||||
if not attrs:
|
||||
attrs = {}
|
||||
if attrs.has_key('widget_class'):
|
||||
widget_class = attrs.get('widget_class')
|
||||
attrs = attrs.copy()
|
||||
del attrs['widget_class']
|
||||
else:
|
||||
widget_class = StringWidget
|
||||
form.add(widget_class, k, title = _(l), **attrs)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('../..')
|
||||
|
||||
if form.is_submitted():
|
||||
sid = form.get_widget('cdg59sid').parse() or ''
|
||||
if sid and misc.simplify(sid) != sid:
|
||||
form.get_widget('cdg59sid').set_error(
|
||||
_('All lowercase, no space or special characters'))
|
||||
|
||||
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('edit', _('Edit')))
|
||||
html_top('services', title = _('New Service Declaration'))
|
||||
'<h2>%s</h2>' % _('New Service Declaration')
|
||||
form.render()
|
||||
else:
|
||||
return self.submit_new(form)
|
||||
|
||||
def submit_new(self, form):
|
||||
values = {}
|
||||
values['cdg59sid'] = form.get_widget('cdg59sid').parse()
|
||||
for k, l, attrs in ServiceDirectory.attrs:
|
||||
widget = form.get_widget(k)
|
||||
if widget:
|
||||
v = widget.parse()
|
||||
if v:
|
||||
values[k] = v
|
||||
directory.add_service(values)
|
||||
return redirect(form.get_widget('cdg59sid').parse() + '/')
|
||||
|
||||
|
||||
|
||||
def _q_lookup(self, component):
|
||||
# lookup for service instance
|
||||
try:
|
||||
service = directory.get_service(component)
|
||||
get_response().breadcrumb.append(('service/' + component + '/', service.cn))
|
||||
return ServiceDirectory(service)
|
||||
except KeyError:
|
||||
raise errors.TraversalError()
|
||||
return Directory._q_lookup(self, component)
|
||||
|
||||
|
||||
|
||||
class ServicesDirectory(Directory):
|
||||
_q_exports = ['', 'service', 'subscribe']
|
||||
|
||||
collectivity = None
|
||||
service = ServiceLookupDirectory()
|
||||
|
||||
def __init__(self, collectivity = None):
|
||||
Directory.__init__(self)
|
||||
self.collectivity = collectivity
|
||||
|
||||
def _q_traverse(self, path):
|
||||
user = get_session().get_user_object()
|
||||
if (user.is_admin() and not self.collectivity) or (not user.is_admin()):
|
||||
get_response().breadcrumb.append(('services/', _('Services Management')))
|
||||
return Directory._q_traverse(self, path)
|
||||
|
||||
def _q_index [html] (self):
|
||||
html_top('services', _('Service Management'))
|
||||
|
||||
user = get_session().get_user_object()
|
||||
if user.is_admin() and not self.collectivity:
|
||||
'<h3>%s</h3>' % _('List of Services')
|
||||
'<ul>'
|
||||
for service in directory.get_services():
|
||||
'<li><a href="service/%s/">' % service.cdg59sid
|
||||
service.cn
|
||||
'</a></li>'
|
||||
'</ul>'
|
||||
|
||||
'<p><a href="service/new">%s</a></p>' % _('Declare new service')
|
||||
|
||||
'<h3>%s</h3>' % _('List of Collectivities')
|
||||
# list all collectivities, but the admin group
|
||||
'<ul>'
|
||||
for collectivity in directory.get_sorted_collectivities():
|
||||
if collectivity.ou == 'admin':
|
||||
continue
|
||||
'<li><a href="%s/">' % collectivity.ou
|
||||
collectivity.cn
|
||||
'</a></li>'
|
||||
'</ul>'
|
||||
else:
|
||||
'<h2>'
|
||||
self.collectivity.cn
|
||||
'</h2>'
|
||||
|
||||
'<p>'
|
||||
if user.is_admin():
|
||||
'<a href="../../identities/%s/">%s</a>' % (
|
||||
self.collectivity.ou, _('Identities Management'))
|
||||
else:
|
||||
'<a href="../identities/">%s</a>' % _('Identities Management')
|
||||
'</p>'
|
||||
|
||||
'<ul class="biglist">'
|
||||
service_instances = directory.get_service_instances(self.collectivity)
|
||||
for service in service_instances:
|
||||
'<li class="biglistitem">'
|
||||
'<strong class="label">%s</strong>' % service.name
|
||||
'<p class="commands">'
|
||||
command_icon('%s/' % service.cdg59siid, 'view')
|
||||
command_icon('%s/edit' % service.cdg59siid, 'edit')
|
||||
command_icon('%s/delete' % service.cdg59siid, 'remove', popup = True)
|
||||
'</p></li>'
|
||||
'</ul>'
|
||||
|
||||
if user.is_admin():
|
||||
all_services = directory.get_services()
|
||||
instanciated_services = [x.cdg59serviceType for x in service_instances]
|
||||
available_services = []
|
||||
for service in all_services:
|
||||
if not service.cdg59sid in instanciated_services:
|
||||
available_services.append((service.cdg59sid, service.cn, service.cdg59sid))
|
||||
|
||||
if available_services:
|
||||
'<div id="new-field">'
|
||||
form = Form(enctype='multipart/form-data', action = 'subscribe')
|
||||
form.widgets.append(HtmlWidget('<table><tr><td>'))
|
||||
form.add(SingleSelectWidget, 'sid', title = _('Subscribe to new service:'),
|
||||
options = available_services)
|
||||
form.widgets.append(HtmlWidget('</td></tr></table>'))
|
||||
form.widgets.append(HtmlWidget(
|
||||
'<p class="commands">%s</p>' % command_icon(None, 'add')))
|
||||
form.render()
|
||||
'</div>'
|
||||
|
||||
if user.is_admin():
|
||||
'<p>'
|
||||
'<a href="../">%s</a>' % _('Back')
|
||||
'</p>'
|
||||
|
||||
def subscribe(self):
|
||||
user = get_session().get_user_object()
|
||||
if not user.is_admin():
|
||||
raise errors.AccessForbiddenError()
|
||||
if not self.collectivity:
|
||||
raise TraversalError()
|
||||
|
||||
all_services = directory.get_services()
|
||||
available_services = [x.cdg59sid for x in all_services]
|
||||
form = Form(enctype='multipart/form-data', action = 'subscribe')
|
||||
form.add(SingleSelectWidget, 'sid', title = _('Subscribe to new service:'),
|
||||
options = available_services, required = True)
|
||||
if form.has_errors() or not form.is_submitted():
|
||||
return redirect('.')
|
||||
|
||||
sid = form.get_widget('sid').parse()
|
||||
|
||||
si = directory.ServiceInstance()
|
||||
si.cdg59siid = sid
|
||||
si.cdg59serviceType = sid
|
||||
associated_service = [x for x in all_services if x.cdg59sid == sid][0]
|
||||
|
||||
si.add(self.collectivity)
|
||||
|
||||
if associated_service.cdg59isGlobal:
|
||||
return redirect('.')
|
||||
else:
|
||||
return redirect(sid + '/edit')
|
||||
|
||||
def _q_lookup(self, component):
|
||||
if not self.collectivity:
|
||||
for collectivity in directory.get_collectivities():
|
||||
if collectivity.ou == component:
|
||||
get_response().breadcrumb.append((component + '/', collectivity.cn))
|
||||
return ServicesDirectory(collectivity)
|
||||
else:
|
||||
# lookup for service instance
|
||||
try:
|
||||
service = directory.get_service_instance(self.collectivity, component)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
return ServiceInstanceDirectory(service)
|
||||
except KeyError:
|
||||
return template.error_page(_('Invalid Service Type (was it removed?)'))
|
||||
raise errors.TraversalError()
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
try:
|
||||
import elementtree.ElementTree as ET
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from quixote import get_request, get_session
|
||||
|
||||
from qommon.publisher import get_publisher, get_publisher_class
|
||||
|
||||
import authentic.sessions
|
||||
|
||||
class PraticIdPSession(authentic.sessions.BasicSession):
|
||||
def get_xml_dir(cls):
|
||||
xml_dir = os.path.join(get_publisher().app_dir, 'sessions-xml')
|
||||
if not os.path.exists(xml_dir):
|
||||
os.makedirs(xml_dir)
|
||||
return xml_dir
|
||||
get_xml_dir = classmethod(get_xml_dir)
|
||||
|
||||
def store(self):
|
||||
authentic.sessions.BasicSession.store(self)
|
||||
session_xml_path = os.path.join(self.get_xml_dir(), self.id)
|
||||
if self.user:
|
||||
node = ET.Element('session')
|
||||
ET.SubElement(node, 'uid').text = self.user
|
||||
fd = file(session_xml_path, 'w')
|
||||
ET.ElementTree(node).write(fd)
|
||||
fd.close()
|
||||
else:
|
||||
if os.path.exists(session_xml_path):
|
||||
os.unlink(session_xml_path)
|
||||
|
||||
def remove_object(cls, id):
|
||||
authentic.sessions.BasicSession.remove_object(id)
|
||||
session_xml_path = os.path.join(cls.get_xml_dir(), id)
|
||||
if os.path.exists(session_xml_path):
|
||||
os.unlink(session_xml_path)
|
||||
remove_object = classmethod(remove_object)
|
||||
|
||||
|
||||
class StorageSessionManager(authentic.sessions.StorageSessionManager):
|
||||
def __init__(self, session_class = PraticIdPSession):
|
||||
authentic.sessions.StorageSessionManager.__init__(self,
|
||||
session_class = PraticIdPSession)
|
||||
|
||||
def expire_session(self):
|
||||
request = get_request()
|
||||
session = get_session()
|
||||
if request.user:
|
||||
user = get_session().get_user_object()
|
||||
agent = user.get_as_agent()
|
||||
agent.cdg59lastConnectionDuration = int(time.time() - session.get_creation_time())
|
||||
try:
|
||||
agent.save(['cdg59lastConnectionDuration'])
|
||||
except:
|
||||
# too bad it failed.
|
||||
pass
|
||||
|
||||
authentic.sessions.StorageSessionManager.expire_session(self)
|
||||
|
||||
get_publisher_class().session_manager_class = StorageSessionManager
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
import sys
|
||||
|
||||
try:
|
||||
import ldap
|
||||
import ldap.async
|
||||
import ldap.modlist
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
import lasso
|
||||
|
||||
from quixote import get_session, get_publisher
|
||||
|
||||
from qommon.form import *
|
||||
from qommon.storage import StorableObject
|
||||
|
||||
from authentic import identities
|
||||
|
||||
import directory
|
||||
|
||||
class IdentitiesStorePratic:
|
||||
label = N_('Pr@tic Directory')
|
||||
admin_keys = ('pratic_ldap_url', 'pratic_ldap_base')
|
||||
|
||||
def is_bootstrapping(self):
|
||||
return False
|
||||
|
||||
def fill_admin_form(self, form, data_source):
|
||||
form.add(StringWidget, 'pratic_ldap_url', title = _('LDAP URL'), required = True,
|
||||
hint = htmltext(_('Example: <tt>ldap://directory.example.com</tt>')),
|
||||
value = data_source.get('pratic_ldap_url', ''))
|
||||
form.add(StringWidget, 'pratic_ldap_base', title = _('LDAP Base'), required = True,
|
||||
hint = htmltext(_('Example: <tt>dc=example, dc=com</tt>')),
|
||||
value = data_source.get('pratic_ldap_base', ''))
|
||||
|
||||
def has_identity(self, uid):
|
||||
try:
|
||||
self.get_identity(uid)
|
||||
except KeyError:
|
||||
return False
|
||||
return True
|
||||
|
||||
def load_identities(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_identity_for_account(self, username, password, collectivity):
|
||||
store = directory.get_store()
|
||||
ldap_conn = ldap.initialize(store.pratic_ldap_url)
|
||||
# python-ldap only accept UTF8 encoded string so to pass string to python-ldap
|
||||
# API you must always .encode('utf8') them.
|
||||
#
|
||||
# String coming from our own application are encoded with
|
||||
# get_publisher().site_charset, so you must decode them before trying to use
|
||||
# them.
|
||||
uid = 'uid=%s,%s' % (ldap.dn.escape_dn_chars(username.decode(get_publisher().site_charset)), collectivity)
|
||||
try:
|
||||
ldap_conn.simple_bind_s(uid.encode('utf8'), password.decode(get_publisher().site_charset).encode('utf8'))
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
return None
|
||||
|
||||
identity = self.get_identity(uid)
|
||||
if identity:
|
||||
agent = identity.get_as_agent()
|
||||
if agent.cdg59isDisabled:
|
||||
return None
|
||||
return identity
|
||||
|
||||
def get_identity_for_name_identifier(self, name_identifier):
|
||||
for i in MiniIdentityPratic.values():
|
||||
if not (i.lasso_dump or i.lasso_proxy_dump):
|
||||
continue
|
||||
if not ((name_identifier in (i.lasso_dump or '')) or (
|
||||
name_identifier in (i.lasso_proxy_dump or ''))):
|
||||
continue # shortcut so it doesn't do the whole thing if not necessary
|
||||
identity = lasso.Identity.newFromDump(i.lasso_dump)
|
||||
for p in identity.providerIds:
|
||||
federation = identity.getFederation(p)
|
||||
if federation.localNameIdentifier and \
|
||||
federation.localNameIdentifier.content == name_identifier:
|
||||
return self.get_identity(i.id)
|
||||
if federation.remoteNameIdentifier and \
|
||||
federation.remoteNameIdentifier.content == name_identifier:
|
||||
return self.get_identity(i.id)
|
||||
|
||||
if i.lasso_proxy_dump:
|
||||
identity = lasso.Identity.newFromDump(i.lasso_proxy_dump)
|
||||
for p in identity.providerIds:
|
||||
federation = identity.getFederation(p)
|
||||
if federation.localNameIdentifier and \
|
||||
federation.localNameIdentifier.content == name_identifier:
|
||||
return i
|
||||
if federation.remoteNameIdentifier and \
|
||||
federation.remoteNameIdentifier.content == name_identifier:
|
||||
return i
|
||||
|
||||
return None
|
||||
|
||||
def init_session(self, session, password):
|
||||
session.pratic_ldap_password = password
|
||||
self._ldap_conn = None
|
||||
|
||||
_ldap_conn = None
|
||||
def get_ldap_conn(self):
|
||||
if self._ldap_conn:
|
||||
return self._ldap_conn
|
||||
|
||||
store = directory.get_store()
|
||||
self._ldap_conn = ldap.initialize(store.pratic_ldap_url)
|
||||
|
||||
session = get_session()
|
||||
if session and hasattr(session, 'pratic_ldap_password'):
|
||||
uid = session.user
|
||||
password = session.pratic_ldap_password
|
||||
try:
|
||||
self._ldap_conn.simple_bind_s(uid, password)
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
pass # XXX?
|
||||
|
||||
return self._ldap_conn
|
||||
ldap_conn = property(get_ldap_conn)
|
||||
|
||||
def connect(self, session):
|
||||
if session and session.user and hasattr(session, 'pratic_ldap_password'):
|
||||
# bind to the LDAP directory so it can access its attributes
|
||||
try:
|
||||
self.ldap_conn.simple_bind_s(session.user,
|
||||
session.pratic_ldap_password)
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
return
|
||||
|
||||
def get_identity(self, uid):
|
||||
try:
|
||||
identity = MiniIdentityPratic.get(uid)
|
||||
except KeyError:
|
||||
identity = MiniIdentityPratic(id = uid)
|
||||
|
||||
return identity
|
||||
|
||||
def save(self, identity):
|
||||
identity.store()
|
||||
|
||||
|
||||
class MiniIdentityPratic(StorableObject):
|
||||
_names = 'pratic_identities'
|
||||
lasso_dump = None
|
||||
lasso_proxy_dump = None
|
||||
resource_id = None
|
||||
|
||||
roles = None
|
||||
accounts = None
|
||||
|
||||
def get_name(self):
|
||||
return str(self.id).split(',')[0].split('=')[1]
|
||||
name = property(get_name)
|
||||
|
||||
def get_locked_down(self):
|
||||
return False
|
||||
locked_down = property(get_locked_down)
|
||||
|
||||
def get_disabled(self):
|
||||
agent = self.get_as_agent()
|
||||
if agent.cdg59isDisabled:
|
||||
return True
|
||||
return False
|
||||
disabled = property(get_disabled)
|
||||
|
||||
def register_new_session(self):
|
||||
agent = self.get_as_agent()
|
||||
session = get_session()
|
||||
session.previousConnectionTime = agent.cdg59lastConnectionTime
|
||||
session.previousConnectionDuration = agent.cdg59lastConnectionDuration
|
||||
agent.cdg59lastConnectionTime = str(int(time.time()))
|
||||
agent.cdg59lastConnectionDuration = None
|
||||
agent.save(['cdg59lastConnectionTime', 'cdg59lastConnectionDuration'])
|
||||
|
||||
def is_admin(self):
|
||||
return ',ou=admin,' in str(self.id)
|
||||
|
||||
def is_local_admin(self):
|
||||
if not 'ou=' in str(self.id):
|
||||
return False
|
||||
store = directory.get_store()
|
||||
ldap_conn = ldap.initialize(store.pratic_ldap_url)
|
||||
try:
|
||||
record = ldap_conn.search_s(str(self.id), ldap.SCOPE_BASE)[0][1]
|
||||
except:
|
||||
return False
|
||||
return 'TRUE' in record.get('cdg59isAdmin', [])
|
||||
|
||||
def get_display_name(self):
|
||||
return self.id[:self.id.index(',')]
|
||||
display_name = property(get_display_name)
|
||||
|
||||
def get_collectivity(self):
|
||||
collectivity_ou = self.id[self.id.index(',')+1:]
|
||||
collectivity_ou = collectivity_ou[:collectivity_ou.index(',')].strip().split('=')[1]
|
||||
return directory.get_collectivity(collectivity_ou)
|
||||
|
||||
def get_attributes(self):
|
||||
agent = self.get_as_agent()
|
||||
attributes = {}
|
||||
for k in ('username', 'cn', 'mail'):
|
||||
v = getattr(agent, k)
|
||||
if v is None:
|
||||
continue
|
||||
attributes[k] = [ unicode(v, 'iso-8859-1'), ]
|
||||
if agent.cdg59isAdmin:
|
||||
attributes['local-admin'] = [ 'true', ]
|
||||
if self.is_admin():
|
||||
attributes['super-admin'] = [ 'true', ]
|
||||
else:
|
||||
attributes['collectivity'] = [ unicode(self.get_collectivity().ou, 'iso-8859-1'), ]
|
||||
return attributes
|
||||
attributes = property(get_attributes)
|
||||
|
||||
_agent = None
|
||||
def get_as_agent(self):
|
||||
if self._agent:
|
||||
return self._agent
|
||||
store = directory.get_store()
|
||||
ldap_conn = ldap.initialize(store.pratic_ldap_url)
|
||||
record = ldap_conn.search_s(self.id, ldap.SCOPE_BASE)[0]
|
||||
self._agent = directory.Agent(record)
|
||||
return self._agent
|
||||
|
||||
def __str__(self):
|
||||
# used for logging
|
||||
if type(self.id) is not str:
|
||||
return ''
|
||||
if not self.id:
|
||||
return ''
|
||||
if not '=' in self.id:
|
||||
# logger system could make self.id be 'unlogged'...
|
||||
return self.id
|
||||
return '/'.join([x.split('=', 1)[1] for x in self.id.split(',')[:2]])
|
||||
|
||||
# don't pickle _agent cache
|
||||
def __getstate__(self):
|
||||
odict = self.__dict__
|
||||
if odict.has_key('_agent'):
|
||||
del odict['_agent']
|
||||
return odict
|
||||
|
||||
def __setstate__(self, dict):
|
||||
self.__dict__ = dict
|
||||
self._agent = None
|
||||
|
||||
|
||||
identities.stores['pratic'] = IdentitiesStorePratic
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
from quixote import get_publisher, get_session
|
||||
|
||||
from qommon.publisher import get_publisher_class
|
||||
import modules.sessions
|
||||
import modules.store
|
||||
import modules.root
|
||||
import modules.backoffice
|
||||
|
||||
|
||||
get_publisher_class().register_translation_domain('pratic')
|
||||
|
||||
def get_admin_help_url(*args):
|
||||
user = get_session().get_user_object()
|
||||
if user and user.is_admin():
|
||||
return {
|
||||
'fr': 'http://wiki.entrouvert.org/Pratic/Guide_de_l%27administrateur_g%C3%A9n%C3%A9ral'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'fr': 'https://wiki.entrouvert.org/Pratic/Guide_de_l%27administrateur_local',
|
||||
}
|
||||
|
||||
get_publisher_class().admin_help_url = property(get_admin_help_url)
|
||||
get_publisher_class().backoffice_help_url = property(get_admin_help_url)
|
|
@ -1,103 +1,5 @@
|
|||
authentic-pratic (1.0.7) pratic; urgency=low
|
||||
authentic-ifef (1.0.0) stable; urgency=low
|
||||
|
||||
* Patches from aeb6585052fb30c2a33625863df07cb6d2584526 to 43b5c68ef0c958df619539a4f2ad62099ab998b8
|
||||
* Check collectivity exists when loading it from cookie
|
||||
* Convert encoding for Collectivity field contained non-ascii characters
|
||||
* update slapd.conf with parameters in production
|
||||
* Accept dots and dashes in usernames
|
||||
* Initial package
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Thu, 03 Dec 2009 12:05:29 +0100
|
||||
|
||||
authentic-pratic (1.0.6) pratic; urgency=low
|
||||
|
||||
* Install theme in correct directory
|
||||
* Correctly pass DN value to LDAP library (that is as UTF-8)
|
||||
* Check character used for new users identifiers
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Thu, 22 Oct 2009 18:58:49 +0200
|
||||
|
||||
authentic-pratic (1.0.5) pratic; urgency=low
|
||||
|
||||
* Forbid to remove service for existing service instances.
|
||||
* Fix access to service instance of global services.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 21 Sep 2009 18:37:35 +0200
|
||||
|
||||
|
||||
authentic-pratic (1.0.4) pratic; urgency=low
|
||||
|
||||
* Make home page not throws when service type of an existing service has
|
||||
been removed.
|
||||
* Signal absenc of the service type when trying to edit a service using this
|
||||
service type.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Fri, 11 Sep 2009 16:17:00 +0200
|
||||
|
||||
authentic-pratic (1.0.3) pratic; urgency=low
|
||||
|
||||
* Check for duplicate sirh/email on edit (seo#55)
|
||||
|
||||
-- Frederic Peters <fpeters@entrouvert.com> Wed, 15 Apr 2009 08:24:17 +0200
|
||||
|
||||
authentic-pratic (1.0.2) pratic; urgency=low
|
||||
|
||||
* Fixed get_collectivity_name function, quote filter arguments only one time.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Tue, 14 Apr 2009 21:26:32 +0200
|
||||
|
||||
authentic-pratic (1.0.1) pratic; urgency=low
|
||||
|
||||
* Fixed display of error page on SSO request from unauthorized SP.
|
||||
|
||||
-- Frederic Peters <fpeters@debian.org> Tue, 14 Apr 2009 18:45:57 +0200
|
||||
|
||||
authentic-pratic (1.0.0-8) pratic; urgency=low
|
||||
|
||||
* Stop unauthorized user right on IdP (beo#267)
|
||||
* Do not fail when displaying the collectivity of an agent whose
|
||||
collectivity is unknown.
|
||||
|
||||
-- Frederic Peters <fpeters@debian.org> Tue, 14 Apr 2009 16:13:32 +0200
|
||||
|
||||
authentic-pratic (1.0.0-7) stable; urgency=low
|
||||
|
||||
* Mise à jour gratuite :)
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 06 Apr 2009 15:37:50 +0200
|
||||
|
||||
authentic-pratic (1.0.0-6) stable; urgency=low
|
||||
|
||||
* Mise à jour des traductions.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 06 Apr 2009 15:25:17 +0200
|
||||
|
||||
authentic-pratic (1.0.0-5) stable; urgency=low
|
||||
|
||||
* Inclu le support des attributs unicode et la gestion des types de
|
||||
services qui disparaissent.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 16 Mar 2009 22:19:51 +0100
|
||||
|
||||
authentic-pratic (1.0.0-4) stable; urgency=low
|
||||
|
||||
* Déjà fait.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 16 Mar 2009 22:19:43 +0100
|
||||
|
||||
authentic-pratic (1.0.0-3) stable; urgency=low
|
||||
|
||||
* Fix missing converion to UTF8 when setting assertions attributes.
|
||||
* Use escaping in ldap filters generated with format.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Tue, 27 Jan 2009 18:02:46 +0100
|
||||
|
||||
authentic-pratic (1.0.0-2) stable; urgency=low
|
||||
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Tue, 27 Jan 2009 16:08:59 +0100
|
||||
|
||||
authentic-pratic (1.0.0-1) stable; urgency=low
|
||||
|
||||
* Initial package.
|
||||
|
||||
-- Damien Laniel <dlaniel@entrouvert.com> Wed, 03 Sep 2008 15:48:49 +0200
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 26 Apr 2010 12:38:27 +0200
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
Source: authentic-pratic
|
||||
Source: authentic-ifef
|
||||
Section: web
|
||||
Priority: optional
|
||||
Maintainer: Frederic Peters <fpeters@entrouvert.com>
|
||||
Maintainer: Benjamin Dauvergne <bdauvergne@entrouvert.com>
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python
|
||||
Build-Depends-Indep: python-support (>= 0.4), gettext, python-quixote
|
||||
Standards-Version: 3.8.0.1
|
||||
XS-Python-Version: current
|
||||
|
||||
Package: authentic-pratic
|
||||
Package: authentic-ifef
|
||||
Architecture: all
|
||||
Depends: ${python:Depends}, authentic, python-ldap
|
||||
Description: Liberty Alliance Identity Server - Pr@tic Extension
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
authentic-pratic_1.0.7_all.deb web optional
|
|
@ -29,9 +29,9 @@ install: build
|
|||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
$(PYTHON) setup.py install --prefix=$(CURDIR)/debian/authentic-pratic/usr --no-compile
|
||||
cd po && make install prefix=$(CURDIR)/debian/authentic-pratic/
|
||||
cp ldap/cdg59.schema $(CURDIR)/debian/authentic-pratic/etc/ldap/schema/
|
||||
$(PYTHON) setup.py install --prefix=$(CURDIR)/debian/authentic-ifef/usr --no-compile
|
||||
cd po && make install prefix=$(CURDIR)/debian/authentic-ifef/
|
||||
# cp ldap/ifef.schema $(CURDIR)/debian/authentic-ifef/etc/ldap/schema/
|
||||
|
||||
|
||||
# Build architecture-independent files here.
|
||||
|
|
Reference in New Issue