1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-08-24 05:57:53 +02:00

Compare commits

..

7 Commits

Author SHA1 Message Date
72806f0ace Add profile and membership information to OAuth views
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 10:57:35 +01:00
b244e01231 Add simple view to give OAuth information
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 10:41:43 +01:00
76d1784aea Add OAuth2 authentication for Django Rest Framework
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:44:25 +01:00
56c5fa4057 We don't need a session to have permissions
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:41:27 +01:00
b5ef937a03 Environment file path is absolute
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:39:57 +01:00
e95a8b6e18 Add normalized name to services
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-03 18:42:51 +01:00
635adf1360 Use cas server to use authentication in other services
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-03 18:13:33 +01:00
19 changed files with 130 additions and 128 deletions

View File

@@ -1,3 +0,0 @@
skip_list:
- command-instead-of-shell # Use shell only when shell functionality is required
- experimental # all rules tagged as experimental

View File

@@ -10,22 +10,50 @@ variables:
# Debian Buster # Debian Buster
py37-django22: py37-django22:
stage: test stage: test
image: otthorn/nk20_ci_37 image: debian:buster-backports
before_script:
- >
apt-get update &&
apt-get install --no-install-recommends -t buster-backports -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py37-django22 script: tox -e py37-django22
# Ubuntu 20.04 # Ubuntu 20.04
py38-django22: py38-django22:
stage: test stage: test
image: otthorn/nk20_ci_38 image: ubuntu:20.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py38-django22 script: tox -e py38-django22
# Debian Bullseye # Debian Bullseye
py39-django22: py39-django22:
stage: test stage: test
image: otthorn/nk20_ci_39 image: debian:bullseye
before_script:
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py39-django22 script: tox -e py39-django22
# Tox linter
linters: linters:
stage: quality-assurance stage: quality-assurance
image: debian:buster-backports image: debian:buster-backports
@@ -36,20 +64,6 @@ linters:
# Be nice to new contributors, but please use `tox` # Be nice to new contributors, but please use `tox`
allow_failure: true allow_failure: true
# Ansible linter
ansible-linter:
stage: quality-assurance
image: otthorn/nk20_ci_ansiblelint
script: ansible-lint ansible/
# Docker linter
docker-linter:
stage: quality-assurance
image: hadolint/hadolint
script:
- hadolint -c .hadolint Dockerfile
- hadolint -c .hadolint docker_ci/Dockerfile.*
# Compile documentation # Compile documentation
documentation: documentation:
stage: docs stage: docs

View File

@@ -1,4 +0,0 @@
ignored:
- DL3008 # Do not force to pin version in apt (Debian)
- DL3013 # Do not force to pin version in pip (PyPI)
- DL3018 # Do not force to pin version in apk (Alpine)

View File

@@ -4,10 +4,14 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework.serializers import ModelSerializer from django.utils import timezone
from rest_framework import serializers
from member.api.serializers import ProfileSerializer, MembershipSerializer
from note.models import Alias
class UserSerializer(ModelSerializer): class UserSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for Users. REST API Serializer for Users.
The djangorestframework plugin will analyse the model `User` and parse all fields in the API. The djangorestframework plugin will analyse the model `User` and parse all fields in the API.
@@ -22,7 +26,7 @@ class UserSerializer(ModelSerializer):
) )
class ContentTypeSerializer(ModelSerializer): class ContentTypeSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for Users. REST API Serializer for Users.
The djangorestframework plugin will analyse the model `User` and parse all fields in the API. The djangorestframework plugin will analyse the model `User` and parse all fields in the API.
@@ -31,3 +35,39 @@ class ContentTypeSerializer(ModelSerializer):
class Meta: class Meta:
model = ContentType model = ContentType
fields = '__all__' fields = '__all__'
class OAuthSerializer(serializers.ModelSerializer):
"""
Informations that are transmitted by OAuth.
For now, this includes user, profile and valid memberships.
This should be better managed later.
"""
normalized_name = serializers.SerializerMethodField()
profile = ProfileSerializer()
memberships = serializers.SerializerMethodField()
def get_normalized_name(self, obj):
return Alias.normalize(obj.username)
def get_memberships(self, obj):
return serializers.ListSerializer(child=MembershipSerializer()).to_representation(
obj.memberships.filter(date_start__lte=timezone.now(), date_end__gte=timezone.now()))
class Meta:
model = User
fields = (
'id',
'username',
'normalized_name',
'first_name',
'last_name',
'email',
'is_superuser',
'is_active',
'is_staff',
'profile',
'memberships',
)

View File

@@ -5,6 +5,7 @@ from django.conf import settings
from django.conf.urls import url, include from django.conf.urls import url, include
from rest_framework import routers from rest_framework import routers
from .views import UserInformationView
from .viewsets import ContentTypeViewSet, UserViewSet from .viewsets import ContentTypeViewSet, UserViewSet
# Routers provide an easy way of automatically determining the URL conf. # Routers provide an easy way of automatically determining the URL conf.
@@ -47,5 +48,6 @@ app_name = 'api'
# Additionally, we include login URLs for the browsable API. # Additionally, we include login URLs for the browsable API.
urlpatterns = [ urlpatterns = [
url('^', include(router.urls)), url('^', include(router.urls)),
url('me', UserInformationView.as_view()),
url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] ]

20
apps/api/views.py Normal file
View File

@@ -0,0 +1,20 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.models import User
from rest_framework.generics import RetrieveAPIView
from .serializers import OAuthSerializer
class UserInformationView(RetrieveAPIView):
"""
These fields are give to OAuth authenticators.
"""
serializer_class = OAuthSerializer
def get_queryset(self):
return User.objects.filter(pk=self.request.user.pk)
def get_object(self):
return self.request.user

15
apps/member/auth.py Normal file
View File

@@ -0,0 +1,15 @@
from cas_server.auth import DjangoAuthUser # pragma: no cover
from note.models import Alias
class CustomAuthUser(DjangoAuthUser): # pragma: no cover
"""
Override Django Auth User model to define a custom Matrix username.
"""
def attributs(self):
d = super().attributs()
if self.user:
d["normalized_name"] = Alias.normalize(self.user.username)
return d

View File

@@ -134,8 +134,6 @@ class PermissionBackend(ModelBackend):
return False return False
sess = get_current_session() sess = get_current_session()
if sess is not None and sess.session_key is None:
return False
if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42: if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42:
return True return True

View File

@@ -1,18 +0,0 @@
FROM debian:buster-backports
LABEL maintainer="otthorn@crans.org"
LABEL description="Debian Buster backports image with django and tox \
installed for testing purposes"
RUN apt-get update \
&& apt-get install --no-install-recommends -t buster-backports -y \
python3-django python3-django-crispy-forms \
python3-django-extensions python3-django-filters \
python3-django-polymorphic \
python3-djangorestframework python3-django-oauth-toolkit \
python3-psycopg2 python3-pil \
python3-babel python3-lockfile python3-pip python3-phonenumbers \
python3-memcache \
python3-bs4 python3-setuptools tox texlive-xetex \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,22 +0,0 @@
FROM ubuntu:20.04
LABEL maintainer="otthorn@crans.org"
LABEL description="Ubuntu 20.04 image with django and tox \
installed for testing purposes"
# fix tzdata prompt
RUN ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
python3-django python3-django-crispy-forms \
python3-django-extensions python3-django-filters \
python3-django-polymorphic \
python3-djangorestframework python3-django-oauth-toolkit \
python3-psycopg2 python3-pil \
python3-babel python3-lockfile python3-pip python3-phonenumbers \
python3-memcache \
python3-bs4 python3-setuptools tox texlive-xetex \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,18 +0,0 @@
FROM debian:bullseye
LABEL maintainer="otthorn@crans.org"
LABEL description="Debian Bulleye image with django and tox \
installed for testing purposes"
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
python3-django python3-django-crispy-forms \
python3-django-extensions python3-django-filters \
python3-django-polymorphic \
python3-djangorestframework python3-django-oauth-toolkit \
python3-psycopg2 python3-pil \
python3-babel python3-lockfile python3-pip python3-phonenumbers \
python3-memcache \
python3-bs4 python3-setuptools tox texlive-xetex \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,10 +0,0 @@
FROM python:3.9-alpine
LABEL maintainer="otthorn@crans.org"
LABEL description="Alpine image with ansible-lint and yamllint \
installed for linting purposes"
RUN apk add --no-cache gcc musl-dev python3-dev libffi-dev openssl-dev cargo
RUN pip install --no-cache-dir "yamllint>=1.26.0,<2.0"
RUN pip install --no-cache-dir "ansible-lint==5.0.0"
RUN pip install --no-cache-dir "ansible>=2.10,<2.11"

View File

@@ -1,8 +0,0 @@
FROM alpine:3.13
LABEL maintainer="otthorn@crans.org"
LABEL description="Alpine image with tox \
installed for linting purposes"
RUN apk --no-cache add py3-pip=20.3.4-r0
RUN pip install --no-cache-dir tox==3.22.0

View File

@@ -1,21 +0,0 @@
# Docker CI
Ce dossier contient les images docker à construire pour la CI. L'idée est
d'avoir une image pré-construire, au dessus laquel il y a besoin de faire
tourner uniquement les commandes qui nous intéresse. Cela permet notamment de
réduire drastiquement le temps que nécessite chaque test car seul la dernière
couche (layer) de l'image a besoin d'etre éxécuter.
## Build les images
Pour build les images il suffit de lancer les commandes suivantes
```
cd docker_ci/
docker build -t nk20_ci_37 -f Dockerfile.37 .
docker build -t nk20_ci_38 -f Dockerfile.38 .
docker build -t nk20_ci_39 -f Dockerfile.39 .
```
Elles sont acutellement build et disponible sur dockerhub
https://hub.docker.com/otthorn/nk20_ci_37

View File

@@ -52,3 +52,9 @@ if "rest_framework" in settings.INSTALLED_APPS:
from rest_framework.authtoken.admin import * from rest_framework.authtoken.admin import *
from rest_framework.authtoken.models import * from rest_framework.authtoken.models import *
admin_site.register(Token, TokenAdmin) admin_site.register(Token, TokenAdmin)
if "cas_server" in settings.INSTALLED_APPS:
from cas_server.admin import *
from cas_server.models import *
admin_site.register(ServicePattern, ServicePatternAdmin)
admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin)

View File

@@ -12,7 +12,7 @@ def read_env():
directory. directory.
""" """
try: try:
with open('.env') as f: with open(os.path.join(BASE_DIR, '.env')) as f:
content = f.read() content = f.read()
except IOError: except IOError:
content = '' content = ''
@@ -30,6 +30,7 @@ def read_env():
# Try to load environment variables from project .env # Try to load environment variables from project .env
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
read_env() read_env()
# Load base settings # Load base settings

View File

@@ -239,6 +239,7 @@ REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [ 'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.TokenAuthentication',
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
], ],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20, 'PAGE_SIZE': 20,
@@ -273,3 +274,6 @@ PIC_RATIO = 1
# Custom phone number format # Custom phone number format
PHONENUMBER_DB_FORMAT = 'NATIONAL' PHONENUMBER_DB_FORMAT = 'NATIONAL'
PHONENUMBER_DEFAULT_REGION = 'FR' PHONENUMBER_DEFAULT_REGION = 'FR'
# We add custom information to CAS, in order to give a normalized name to other services
CAS_AUTH_CLASS = 'member.auth.CustomAuthUser'

View File

@@ -45,6 +45,11 @@ if "oauth2_provider" in settings.INSTALLED_APPS:
path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')) path('o/', include('oauth2_provider.urls', namespace='oauth2_provider'))
) )
if "cas_server" in settings.INSTALLED_APPS:
urlpatterns.append(
path('cas/', include('cas_server.urls', namespace='cas_server'))
)
if "debug_toolbar" in settings.INSTALLED_APPS: if "debug_toolbar" in settings.INSTALLED_APPS:
import debug_toolbar import debug_toolbar
urlpatterns = [ urlpatterns = [

View File

@@ -1,6 +1,7 @@
beautifulsoup4~=4.7.1 beautifulsoup4~=4.7.1
Django~=2.2.15 Django~=2.2.15
django-bootstrap-datepicker-plus~=3.0.5 django-bootstrap-datepicker-plus~=3.0.5
django-cas-server~=1.2.0
django-colorfield~=0.3.2 django-colorfield~=0.3.2
django-crispy-forms~=1.7.2 django-crispy-forms~=1.7.2
django-extensions~=2.1.4 django-extensions~=2.1.4