Skip to content

Commit

Permalink
Merge branch 'develop' into feature/wordcloud-chartjs
Browse files Browse the repository at this point in the history
  • Loading branch information
lukavdplas authored Oct 31, 2023
2 parents 359f3a2 + 60211ce commit 90db7ed
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 3 deletions.
2 changes: 2 additions & 0 deletions backend/ianalyzer/settings_saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,5 @@
'url': [('https://dig.hum.uu.nl', 'en')],
},
}

SAML_GROUP_NAME = 'uu'
26 changes: 26 additions & 0 deletions backend/users/migrations/0005_saml_user_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.db import migrations
from users.saml import saml_user_group

def add_saml_users_to_group(apps, schema_editor):
CustomUser = apps.get_model('users', 'CustomUser')

saml_users = CustomUser.objects.filter(saml = True)
saml_group = saml_user_group()

if saml_group:
for user in saml_users:
user.groups.add(saml_group)
user.save()

class Migration(migrations.Migration):

dependencies = [
('users', '0004_userprofile'),
]

operations = [
migrations.RunPython(
add_saml_users_to_group,
reverse_code=migrations.RunPython.noop
)
]
12 changes: 12 additions & 0 deletions backend/users/saml.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
from djangosaml2.backends import Saml2Backend
from django.contrib.auth.models import Group
from django.conf import settings

class CustomSaml2Backend(Saml2Backend):
def get_or_create_user(self, *args, **kwargs):
user, created = super().get_or_create_user(*args, **kwargs)
user.saml = True

saml_group = saml_user_group()
if saml_group:
user.groups.add(saml_group)

return user, created

def saml_user_group():
group_name = getattr(settings, 'SAML_GROUP_NAME', None)
if group_name:
return Group.objects.get_or_create(name=group_name)
12 changes: 10 additions & 2 deletions backend/visualization/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ def get_filters(query):

def is_date_filter(filter):
"""Checks if a filter object is a date filter"""
return has_path(filter, 'range', 'date')
range_filters = filter.get('range', dict()).keys()
return any(
has_path(filter, 'range', filter_name, 'format')
for filter_name in range_filters
)


def parse_date(datestring):
Expand All @@ -145,7 +149,11 @@ def get_date_range(query: Dict):
datefilters = list(filter(is_date_filter, filters))

if len(datefilters):
parameters = [f['range']['date'] for f in datefilters]
parameters = [
data
for f in datefilters
for data in f['range'].values()
]
min_dates = [parse_date(p['gte'])
for p in parameters if 'gte' in p]
max_dates = [parse_date(p['lte'])
Expand Down
37 changes: 37 additions & 0 deletions backend/visualization/tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,40 @@ def test_manipulation_is_pure(basic_query):
assert query.get_date_range(basic_query) == (None, None)
assert query.get_date_range(narrow_query) == narrow_timeframe
assert query.get_date_range(wide_query) == wide_timeframe

def test_is_date_filter():
assert query.is_date_filter({
'range': {
'date': {
'gte': '1950-01-01',
'lte': '1959-12-31',
'format': 'yyyy-MM-dd'
}
}
})

assert query.is_date_filter({
'range': {
'publication_date': {
'gte': '1950-01-01',
'lte': '1959-12-31',
'format': 'yyyy-MM-dd'
}
}
})

assert not query.is_date_filter({
'range': {
'year': {
'gte': 1950,
'lte': 1959,
}
}
})

def test_get_date_range():
min_date = datetime(1800, 1, 1)
max_date = datetime(1900, 1, 1)
date_filter = query.make_date_filter(min_date, max_date, 'publication_date')
q = query.add_filter(query.MATCH_ALL, date_filter)
assert query.get_date_range(q) == (min_date, max_date)
6 changes: 6 additions & 0 deletions documentation/SAML.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# SAML

In order to login with Solis ID, I-analyzer has SAML integration with ITS. For this, it uses the [djangosaml2 library](https://djangosaml2.readthedocs.io/). More information on working with SAML, setting up a local environment to test the SAML integration, etc. can be found [here](https://github.com/UUDigitalHumanitieslab/dh-info/blob/master/SAML.md)

The urls exposed by DjangoSaml2 are included as part of our `users` application, e.g., `<hostname>/users/saml2/login`. DjangoSaml2 takes care of consuming the response from the Identity Provider and logging in the user. The `SAML_ATTRIBUTE_MAPPING` variable contains a dictionary of the data coming in from the identity provider, e.g., `uushortid`, and translating that to the corresponding column in the user table, e.g., `username`. Moreover, the setting `SAML_CREATE_UNKNOWN_USER = True` makes sure that we create a user in our database if it's not present yet.

The only tweaks added on top of the DjangoSaml2 package are:
- the logic to set the `saml` column to `True` for a user logging in with SAML. The `CustomSaml2Backend` overrides DjangoSaml2's `get_or_create_user` function to take care of this. Note that in the future, we could also turn this field into a `CharField` to keep track of multiple identity providers here.
- overriding DjangoSaml2's `LogoutView` to make its `post` method `csrf_exempt`. The response from the ITS Identity Provider does not send the csrf cookie in a way that it can be consumed by Django at the moment.

### Authorisation

If you define a `SAML_GROUP_NAME` in settings, SAML users will always be added to a group with that name when they create an account. (The group will be created if it does not exist.) This can be used to give permissions to SAML users. The group is not used to handle authentication, so you can add non-SAML users to it as well.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "i-analyzer",
"version": "5.0.1",
"version": "5.1.0",
"license": "MIT",
"scripts": {
"postinstall": "yarn install-back && yarn install-front",
Expand Down

0 comments on commit 90db7ed

Please sign in to comment.