Projet

Général

Profil

0001-allow-customizing-setting-user-id-in-session-fixes-1.patch

Benjamin Dauvergne, 07 mars 2017 10:53

Télécharger (6,35 ko)

Voir les différences:

Subject: [PATCH] allow customizing setting user id in session (fixes #15191)

 mellon/adapters.py                        |   4 ++
 mellon/metadata.py                        | 109 ++++++++++++++++++++++++++++++
 mellon/templates/mellon/mellon_error.html |  11 +++
 mellon/views.py                           |  12 +++-
 4 files changed, 135 insertions(+), 1 deletion(-)
 create mode 100644 mellon/metadata.py
 create mode 100644 mellon/templates/mellon/mellon_error.html
mellon/adapters.py
297 297
                self.logger.info(u'removing group %s (%s) from user %s (%s)', rel.group,
298 298
                                 rel.group.pk, rel.user, rel.user.pk)
299 299
            qs.delete()
300

  
301
    def login(self, request, user):
302
        auth.login(request, user)
303
        return True
mellon/metadata.py
1
import datetime
2
from xml.etree import ElementTree as ET
3
import logging
4
import threading
5

  
6
import requests
7
import isodate
8

  
9
from django.core.files.storage import default_storage
10
from django.utils.timezone import now
11

  
12

  
13
class MetadataException(RuntimeError):
14
    pass
15

  
16

  
17
class Metadata(object):
18
    doc = None
19
    cache_duration = None
20
    valid_until = None
21
    __cache = {}
22
    url = None
23
    path = None
24
    timeout = 10
25

  
26
    def __init__(self, url=None, path=None, content=None, timeout=None):
27
        self.url = url or self.url
28
        self.path = path or self.path
29
        self.timeout = timeout or self.timeout
30

  
31
        if url:
32
            self.load_from_url()
33
        elif path:
34
            self.load_from_path()
35
        else:
36
            self.load_content(content)
37

  
38
    def load_content(self, content):
39
        self.doc = ET.fromstring(content)
40
        try:
41
            self.cache_duration = isodate.parse_duration(
42
                self.doc.attrib.get('cacheDuration'))
43
        except:
44
            self.cache_duration = datetime.timedelta(seconds=30)
45
        try:
46
            self.valid_until = isodate.parse_datetime(
47
                self.doc.attrib.get('validUntil'))
48
        except:
49
            self.valid_until = None
50

  
51
    @property
52
    def cache_path(self):
53
        return 'metadata_cache_' + self.url.replace('/', '_')
54

  
55
    @property
56
    def cache_exists(self):
57
        return default_storage.exists(self.cache_path)
58

  
59
    @property
60
    def cache_timestamp(self):
61
        return default_storage.created_time(self.cache_path)
62

  
63
    def retrieve_url(self):
64
        logger = logging.getLogger(__name__)
65
        try:
66
            response = requests.get(self.url, timeout=self.timeout)
67
            response.raise_for_status()
68
        except requests.RequestException as e:
69
            if self.cache_exists:
70
                logger.warning(u'unable to retrieve metadata from %s, using filesystem cache: %s',
71
                               self.url, e)
72
                return self.cache_timestamp, default_storage.open(self.cache_path).read()
73
            logger.error(u'unable to retrieve metadata from %s, and no filesystem cache: %s',
74
                         self.url, e)
75
            raise MetadataException('unable to retrieve uncached metadata from URL')
76
        else:
77
            content = response.content
78
            if self.cache_exists:
79
                default_storage.delete(self.cache_path)
80
            default_storage.save(self.cache_path, content)
81
            self.load_content(content)
82
            self.__cache[self.url] = now(), content
83

  
84
    def should_update(self, timestamp):
85
        if now() - timestamp < self.cache_duration:
86
            return False
87
        return not self.valid_until or now() > self.valid_until
88

  
89
    def background_update(self):
90
        try:
91
            self.retrieve_url()
92
        except:
93
            pass
94

  
95
    def load_from_url(self):
96
        # 1. check memory cache
97
        #  - if absent synchronously retrieve URL
98
        if self.url not in self.__cache:
99
            self.retrieve_url()
100
            timestamp, content = self.__cache[self.url]
101
        else:
102
            timestamp, content = self.__cache[self.url]
103
            self.load_content(content)
104
            if self.should_update(timestamp):
105
                timestamp = (now() - self.cache_duration + 3 *
106
                             datetime.timedelta(seconds=self.timeout))
107
                self.__cache[self.url] = timestamp, content
108
                t = threading.Thread(target=self.background_update)
109
                t.start()
mellon/templates/mellon/mellon_error.html
1
{% extends "mellon/base.html" %}
2
{% load i18n %}
3

  
4
{% block mellon_content %}
5
<p>
6
   <span class="mellon-error-message">{{ mellon_error_message }}</span>
7
</p>
8
<!--
9
{{ saml_attributes|pprint }}
10
-->
11
{% endblock %}
mellon/views.py
189 189
        next_url = self.get_next_url(default=resolve_url(settings.LOGIN_REDIRECT_URL))
190 190
        if user is not None:
191 191
            if user.is_active:
192
                auth.login(request, user)
192
                for adapter in utils.get_adapters():
193
                    if adapter.login(request, user):
194
                        break
195
                else:
196
                    self.log.warning('no adapter accepted to login login user %r', attributes)
197
                    return render(
198
                        request, "mellon/mellon_error.html",
199
                        {
200
                            'mellon_error_message': 'No adapter accepted to login the user',
201
                        }
202
                    )
193 203
                self.log.info('user %r (NameID is %r) logged in using SAML', unicode(user),
194 204
                              attributes['name_id_content'])
195 205
                request.session['mellon_session'] = utils.flatten_datetime(attributes)
196
-