Gitlab CSE Unil

authentication.py 3.65 KB
Newer Older
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
from django.contrib.auth import login as auth_login
from django.contrib.auth.models import User
from django.db import IntegrityError

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

from .utils import get_request_attp

try:
    from shibauth.models import ShibbUserAttributes
except ImportError:
    ShibbUserAttributes = None


def get_or_create_user(attp_user):
    """
    Try to find an existing user corresponding to the parameters passed by attp_user.
    The first attribute with data in attp_user will be used for lookup
    :param attp_user:
    :return:
    """
    # attp_attr is the name of the attribute in attp_user,
    # model_attr is the corresponding attribute name on the User model,
    # given in attr_choice as (attp_attr, model_attr)
    attr_choice = (('id', 'pk'), ('uniqueId', 'shibbuserattributes__uid'), ('email', 'username'))

    # Lookup the user, using the various attributes
    user = None
    add_uniqueid = False
    for (attp_attr, model_attr) in attr_choice:
        # The attribute was not provided in the message, continue with next attribute
        if not attp_user.get(attp_attr):
            continue

        # If the user cannot be found with the current attribute, try with the next ones
        try:
            user = User.objects.get(**{"{}__iexact".format(model_attr): attp_user.get(attp_attr)})
        except User.DoesNotExist:
            continue

        add_uniqueid = (model_attr != 'shibbuserattributes__uid')
        # user is found, get out of the loop
        break
    user_changed = False

    # If the user could not be found, create it
    if user is None:
        user = User(username=attp_user.get('email'), email=attp_user.get('email'))
        user_changed = True

    # Update User data
    if attp_user.get('first_name') and user.first_name != attp_user['first_name']:  # Update first_name, if provided
        user.first_name = attp_user['first_name']
        user_changed = True

57
    if attp_user.get('last_name') and user.last_name != attp_user['last_name']:  # Update last_name if provided
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
        user.last_name = attp_user['last_name']
        user_changed = True

    if attp_user.get('email') and user.email != attp_user['email']:  # Update email and username if provided
        user.email = user.username = attp_user['email']
        user_changed = True

    if user_changed:
        user.save()

    # Save uniqueId if user has not already one and a value is given
    if add_uniqueid and attp_user.get('uniqueId') and ShibbUserAttributes:
        try:
            ShibbUserAttributes.objects.create(user=user, uid=attp_user.get('uniqueId'))
        except IntegrityError:
            pass

    return user


def login_attp_user(request, attp_message, persist=True):
    """
    Authenticate a user based on the data given in attp_message['user']
    The attp_message is considered valid

    :param request:
    :param attp_message:
    :return:
    """
    attp_user = attp_message.get('user')
    if not attp_user:
        return

    user = get_or_create_user(attp_user)
    if request.user.is_anonymous() or request.user != user:
        if persist:
            user.backend = 'django.contrib.auth.backends.ModelBackend'
            auth_login(request, user)
        else:
            request.user = user


class TTPAuthentication(BaseAuthentication):
    """

    """

    def authenticate(self, request):

        attp_message = get_request_attp(request)
        if not attp_message:
            return None

        attp_user = attp_message.get('user')
        if not attp_user:
            return None

        user = get_or_create_user(attp_user)
        return user, None