summaryrefslogtreecommitdiffstats
path: root/django/sp_sso/saml/utils.py
blob: 5ff35028a6cc0c5f4490a1bf400588dd6cb9ccb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import ldap
import json
import logging

from urllib2 import build_opener, urlopen, HTTPHandler, Request, HTTPError
from random import randint
from django.utils.translation import ugettext as _
from django.shortcuts import render

rootdn = 'dc=condorcet,dc=dev,dc=entrouvert,dc=org'
people_base = 'ou=people,'+rootdn
structures_base = 'ou=structures,'+rootdn
groups_base = 'ou=Groups,'+rootdn
scope = ldap.SCOPE_SUBTREE

logger = logging.getLogger('sp_sso.resource')

sso_attributes = [
    'prenom', 'nom', 'email', 'ep_principal_name', 'ep_primary_affiliation',
    'ep_affiliation', 's_etablissement', 's_entite_affectation_principale',
    's_entite_affectation', 's_emp_corps', 'hote_unite', 'hote_etablissement',
    's_liste_rouge', 'hote_commentaire']

sso_select_attributes = [
    'ep_primary_affiliation', 's_emp_corps', 'hote_unite', 'hote_etablissement']

supann_host_role_attribute = 'supannRoleGenerique'
supann_host_role_value = '{SUPANN}R10' # 'Responsable de mission'


def render_message(request, message):
    return render(request, 'simple_message.html', {'message': message})

def generate_eppn(lastname):
    return "%s-%06d@campus-condorcet.fr"%(lastname, randint(0,pow(10,6)))


def craft_user_nickname(mellon_dict):
    prenom = mellon_dict.get('prenom')[0]
    nom = mellon_dict.get('nom')[0]
    return " "+prenom+" "+nom


def ldap_init():
    # The server's hostname:
    server = "condorcet.dev.entrouvert.org"
    # Admin DN:
    who = "cn=admin,dc=condorcet,dc=dev,dc=entrouvert,dc=org"
    # Credentials: XXX
    cred = "test"

    try:
        l = ldap.open(server)
        l.simple_bind(who, cred)
    except ldap.LDAPError:
        logger.error('Error while binding to the OpenLDAP server.')
        l = None
    return l


def ldap_get_etablissements():
# Used to fill the choices in hote_etablissemnt form ChoiceField:
    return ldap_get_attribute_from_subtree_nodes(
        structures_base, '(objectClass=supannOrg)', 'ou')


def ldap_get_unites():
# Used to fill the choices in hote_unite form ChoiceField:
    return ldap_get_attribute_from_subtree_nodes(
        structures_base, '(supannTypeEntite=*)', 'ou')


def ldap_get_affectations():
# Used to fill the choices in s_entite_affectation_principale form ChoiceField:
    return ldap_get_attribute_from_subtree_nodes(
        structures_base, '(objectClass=supannEntite)', 'supannCodeEntite')


def ldap_get_attribute_from_subtree_nodes(subtree_base, filter, attribute):
    l_handle = ldap_init()
    if not l_handle:
        return []

    res = l_handle.search(subtree_base, scope, filter)
    rtype, rdata = l_handle.result(res, 1)
    ldap_terminate(l_handle)

    choices = []

    # Extra 'null' choice
    choices.append((None, '------------'))

    for node in rdata:
        node_data = node[1]
        attribute_list = node_data.get(attribute)
        if attribute_list:
            attribute_value = attribute_list[0] # No need for multi-valued attributes
                                          # at the moment
        description =  node_data.get('description', [_('No description')])[0]
        choices.append((attribute_value, description))

    return choices

def ldap_terminate(l):
    l.unbind()

def ldap_contains_user(user_data):
    # The way we derive UIDs from the id dict
    #   is defined in ldap_craft_uid:
    rdata = None
    if user_data.get('ep_principal_name'):
        #filter = "uid="+user_data['ep_principal_name']
        filter = "eduPersonPrincipalName={}".format(user_data.get('ep_principal_name'))
        logger.info('Filter : {}'.format(filter))

        l = ldap_init()

        # Look for a user possessing the same uid:
        res = l.search(people_base, scope, filter, None)
        rtype, rdata = l.result(res, 0)

        ldap_terminate(l)

    logger.info('Data : {}'.format(rdata))

    # Does this user already is in the LDAP directory ?
    return 1 if rdata else 0


def saml_collect_data(request):
    form = {}

    # Build the SSO operation summary:
    if 'mellon_session' in request.session: 
        data = request.session['mellon_session']
        for attribute in sso_attributes:
            if data.get(attribute):
                attribute_element = data.get(attribute)[0]
                form[attribute] = attribute_element

    return form

def wcs_submit(user_data, posturl):
    opener = build_opener(HTTPHandler)
    # Generate a JSON to bind against the wcs ReST API
    form = {}
    form["data"] = user_data # see wcs documentation
    data = json.dumps(form)

    req = Request(posturl, data)
    req.add_header("Content-Type", "application/json")
    req.add_header("Accept", "application/json")

    try:
        opener.open(req)
    except HTTPError, e:
        logger.error('HTTP error %d during WCS form submission'%(e.code))

def initial_from_tracking_code(tracking_code):
    if not tracking_code:
        return {}
    base_url = "http://forms-condorcet.dev.entrouvert.org/api/code/"
    tracking_url = base_url+tracking_code
    try:
        req = urlopen(tracking_url)
        response_string = req.read()
    except:
        logger.error('Wrong tracking code.')
        return {}

    try:
        response_dict = json.loads(response_string)
        form_url = response_dict.get('url')
        form_list = form_url.split('/')
        form_number = form_list.pop()
        req = urlopen(
            'http://forms-condorcet.dev.entrouvert.org/api/forms/invitation/'\
            +form_number)
        initial_response = json.loads(req.read())
        # Add comments aimed at w.c.s. backoffice agents
        initial_response.get('fields', {}).update(
            {'hote_commentaire': 'Identite de l\'invitant : %s %s %s' % (
                    initial_response.get('fields', {}).get('hote_prenom'),
                    initial_response.get('fields', {}).get('hote_nom'),
                    initial_response.get('fields', {}).get('hote_courriel'))})
    except:
        return {}

    return initial_response.get('fields', {})