Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
78d5afe
chore: move backend to new directory
michigg Mar 28, 2020
ffd733d
chore: init vue
michigg Mar 29, 2020
4d53666
chore: update docker setup. Improve for future vue implementation
michigg Apr 10, 2020
2bb54d5
chore: add test data generation script
michigg Apr 10, 2020
91e3613
chore: implement drf
michigg Apr 10, 2020
d29b093
chore: init lama api
michigg Apr 10, 2020
8838c90
chore: migrate user group update functions
michigg Apr 10, 2020
23cc91b
chore: migrate groups views
michigg Apr 10, 2020
dd0ca46
chore: implement user list endpoint
michigg Apr 14, 2020
a2c0577
chore: implement mail endpoints
michigg Apr 14, 2020
f8a473a
chore: implement jwt token
michigg Apr 29, 2020
c8d0e28
chore: add test user with default permission
michigg Apr 29, 2020
571b311
chore: add docker frontend configs
michigg Apr 29, 2020
67ef15b
chore: implement casl, authentication and add admin sidebar
michigg Apr 29, 2020
b7d89e1
fix: perrmission denied errors
Apr 29, 2020
5d02e73
chore: implement login
Apr 29, 2020
53fa888
chore: implement user and admin base page selection
Apr 29, 2020
369b0b5
chore: implement realm and realms pages; implement permission denied …
Apr 29, 2020
4cc07d6
chore: remove unused nav item
Apr 29, 2020
1cfa362
chore: implement first about page draft
Apr 29, 2020
ed3aa96
chore: imporve realm tables
Apr 29, 2020
5e97087
chore: start implement users, groups, user and group view
Apr 29, 2020
2967f0e
chore: begin implement user, group view
Apr 30, 2020
37e3aeb
chore: update about page
Apr 30, 2020
f8821d6
chore: add realm views
May 5, 2020
7ff4b8b
chore: reimplement ui functions
Sep 25, 2020
577fbdd
chore: implement repository pattern
Oct 28, 2020
aa4fd3c
chore: add login e2e tests
Oct 28, 2020
839daf7
chore: update packages to latest version
Oct 28, 2020
97a24bd
chore: implement linter rules
Oct 29, 2020
5b9199c
chore: introduce es6 classes
Oct 31, 2020
cdc64d1
chore: reimplement authentication flow
Nov 4, 2020
18da597
fix: retrieve token returns empty token on successfully saved token
Nov 4, 2020
2b1ba95
chore: move realm components to realms package
Nov 4, 2020
b70a1cc
chore: implement scss files, add background color
Nov 4, 2020
a442ef0
fix: always empty abilites
Nov 4, 2020
67561cc
refractor: move independent packages to app folder
Nov 9, 2020
776f3cc
refractor: move users app to app directory
Nov 10, 2020
d68cbd3
chore: remove remove email column from table; It is unsupported in fu…
Nov 10, 2020
4cc18dd
chore: implement new realm frontend model
Nov 10, 2020
b660ebe
refractor: remove old frontend templates
Feb 8, 2021
2ce9ce9
chore: add base user views
Feb 8, 2021
2649792
chore: switched to vue 3 with ts
Feb 11, 2021
a71fb4c
chore: add pwa support
Feb 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
File renamed without changes.
File renamed without changes.
3,598 changes: 3,598 additions & 0 deletions backend/coverage-reports/coverage-python.xml

Large diffs are not rendered by default.

File renamed without changes.
4 changes: 3 additions & 1 deletion docker-compose.test.yml → backend/docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ services:
depends_on:
- ci_dblama
- ci_ldap
volumes:
- ./coverage-reports:/coverage-reports
ports:
- 0.0.0.0:8888:80

ci_dblama:
image: postgres:11.2-alpine
networks:
Expand Down
58 changes: 58 additions & 0 deletions backend/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# DEV SETUP!
version: "3"

networks:
pg_db:
external: false
ldap_net:
external: false

services:
api:
image: lama:0.1
build:
context: docker/lama
dockerfile: Dockerfile.dev
networks:
- ldap_net
- pg_db
env_file:
- docker/lama/dev.env
volumes:
- ./src:/lama
- ./coverage-reports:/coverage-reports
depends_on:
- db
- ldap
ports:
- 0.0.0.0:8000:80

db:
image: postgres:11.2-alpine
networks:
- pg_db
volumes:
- ./db/pgdata/:/var/lib/postgresql/data/
env_file:
- docker/lama/dev.env

ldap:
image: docker.clkl.de/ldap/ldap:0.3-lama
build:
context: docker/ldap
dockerfile: Dockerfile.ldap
env_file: docker/ldap/ldap.env
networks:
- ldap_net

ldap_admin:
image: docker.clkl.de/ldap/admin:0.1-lama
build:
context: docker/ldap
dockerfile: Dockerfile.admin
networks:
- ldap_net
depends_on:
- ldap
ports:
- 0.0.0.0:8888:80
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ WORKDIR /lama
EXPOSE 80

COPY entrypoint.sh /
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
#CMD ["/entrypoint.sh"]
RUN chmod +x /entrypoint.sh

#CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
CMD ["/entrypoint.sh"]
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ FROM alpine:3.9
ADD ["docker/lama/requirements.txt", "/requirements.txt"]
RUN apk upgrade --update && \
apk add --update python3 build-base openldap-dev python3-dev py3-psycopg2 && \
pip3 install -r /requirements.txt && rm /requirements.txt
pip3 install -r /requirements.txt && rm /requirements.txt && \
pip3 install coverage
WORKDIR /lama
EXPOSE 80

#ENTRYPOINT ["python3", "manage.py"]
ADD ["./src", "/lama"]
ADD ["./docker/lama/entrypoint.sh", "/lama/entrypoint.sh"]
ADD ["./docker/lama/entrypoint.test.sh", "/lama/entrypoint.sh"]
RUN chmod +x /lama/entrypoint.sh
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]
2 changes: 1 addition & 1 deletion docker/lama/dev.env → backend/docker/lama/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SITE_NAME=LAMa
SECRET_KEY=supersecret
ALLOWED_HOSTS=localhost

DATABASE_HOST=dblama
DATABASE_HOST=db
DATABASE_PORT=5432

POSTGRES_USER=lama
Expand Down
9 changes: 9 additions & 0 deletions backend/docker/lama/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh
echo "-------- make migrations --------"
python3 /lama/manage.py makemigrations account_helper
echo "-------- migrate --------"
python3 /lama/manage.py migrate
echo "-------- generate test data --------"
python3 /lama/manage.py generate_test_data
echo "-------- start server --------"
python3 /lama/manage.py runserver 0.0.0.0:80
4 changes: 3 additions & 1 deletion docker/lama/entrypoint.sh → backend/docker/lama/entrypoint.test.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ python3 /lama/manage.py makemigrations account_helper
echo "-------- migrate --------"
python3 /lama/manage.py migrate
echo "-------- start test --------"
python3 /lama/manage.py test
coverage run /lama/manage.py test
echo "-------- write test report --------"
coverage xml -i -o /coverage-reports/coverage.xml
File renamed without changes.
10 changes: 10 additions & 0 deletions backend/docker/lama/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Django==3.0.3
django-auth-ldap==2.1.0
django-ldapdb==1.4.0
Jinja2==2.10.3
djangorestframework==3.11.0
djangorestframework-simplejwt==4.4.0
django-cors-headers==3.2.1
PyYAML==5.3.1
uritemplate==3.0.1
drf-yasg==1.17.1
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
FROM alpine:3.9
FROM alpine:3.11

ENV LDAP_PACKAGE_NAME OPENLDAP_REL_ENG_2_4_49

RUN apk add --upgrade --no-cache build-base groff libtool openldap openssl-dev cyrus-sasl-dev util-linux-dev

WORKDIR /openldap
RUN wget https://github.com/openldap/openldap/archive/OPENLDAP_REL_ENG_2_4_47.zip\
&& unzip -d /openldap OPENLDAP_REL_ENG_2_4_47.zip\
&& rm OPENLDAP_REL_ENG_2_4_47.zip\
&& mv openldap-OPENLDAP_REL_ENG_2_4_47/* .\
&& rm -r openldap-OPENLDAP_REL_ENG_2_4_47/
RUN wget https://github.com/openldap/openldap/archive/${LDAP_PACKAGE_NAME}.zip \
&& unzip -d /openldap ${LDAP_PACKAGE_NAME}.zip\
&& rm ${LDAP_PACKAGE_NAME}.zip\
&& mv openldap-${LDAP_PACKAGE_NAME}/* .\
&& rm -r openldap-${LDAP_PACKAGE_NAME}/

RUN ./configure --prefix=/usr \
--sysconfdir=/etc \
Expand Down Expand Up @@ -37,7 +39,7 @@ RUN make depend \
&& make \
&& make prefix=/usr libexec=/usr/lib -C contrib/slapd-modules/lastbind \
&& make install \
&& make prefix=/usr libexec=/usr/lib -C contrib/slapd-modules/lastbind install
&& make prefix=/usr libexec=/usr/lib -C contrib/slapd-modules/lastbind install


#RUN adduser ldap -D
Expand All @@ -61,6 +63,7 @@ RUN sed -i s/dc:\ $dc/dc:\ $dcr/g /etc/openldap/start.ldif
ADD slapd.conf /etc/openldap/slapd.conf
RUN chown ldap:ldap -R /etc/openldap
RUN chown ldap:ldap -R /var/lib/openldap
RUN chmod +x /entrypoint.sh

EXPOSE 389

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Django==3.0.3
python-ldap==3.2.0
django-auth-ldap==2.1.0
django-ldapdb==1.4.0
Jinja2==2.10.3
djangorestframework==3.11.0
django-cors-headers==3.2.1
PyYAML==5.3.1
uritemplate==3.0.1
drf-yasg==1.17.1
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def handle(self, *args, **options):
LdapUser.base_dn = LdapUser.ROOT_DN
ldap_user = LdapUser.objects.get(dn=deletable.ldap_dn)
ldap_user.delete_complete()
except ObjectDoesNotExist as err:
except ObjectDoesNotExist:
self.stdout.write(self.style.ERROR(f"User with the username {options['fduser']} not found."))
return
elif not options['all'] and not options['fduser']:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.contrib.auth.models import User, Permission
from django.core.management.base import BaseCommand

from account_helper.models import Realm
from account_manager.models import LdapGroup, LdapUser


class Command(BaseCommand):
help = 'Generate test data'

def handle(self, *args, **options):
try:
admin = User.objects.create_superuser(username="admin", email="admin@admin.de", password="2malDrei")
admin.is_superuser = True
admin.is_active = True
admin.is_staff = True
admin.is_admin = True
admin.save()
except Exception:
admin = User.objects.get(username="admin")

wiai = Realm.objects.create(name="WIAI", ldap_base_dn="ou=wiai,ou=fachschaften,dc=test,dc=de",
email="test@root.de")
Realm.objects.create(name="SOWI", ldap_base_dn="ou=sowi,ou=fachschaften,dc=test,dc=de")
Realm.objects.create(name="HUWI", ldap_base_dn="ou=huwi,ou=fachschaften,dc=test,dc=de")

ldap_user, user = LdapUser.create_with_django_user(realm=wiai,
username="test",
email="test@test.de",
password="2malDrei")
ldap_group = LdapGroup.full_create(wiai, name="TestGroup", members=[ldap_user.dn])
django_group = ldap_group.get_django_group()

permission = Permission.objects.get(codename="add_deleteduser")
django_group.permissions.add(permission)
django_group.save()
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
from django.conf import settings
from django.contrib.auth.models import Group, User
from django.db import models
from django.utils import timezone
from django.conf import settings


# Create your models here.
from account_helper.validators import validate_ldap_base_dn


class Realm(models.Model):
name = models.CharField(max_length=200, unique=True)
email = models.CharField(max_length=200)
admin_group = models.ForeignKey(Group, models.PROTECT, blank=True, null=True, related_name='admin_groups')
default_group = models.ForeignKey(Group, models.PROTECT, blank=True, null=True, related_name='default_groups')
ldap_base_dn = models.CharField(max_length=400, unique=True)
ldap_base_dn = models.CharField(max_length=400, unique=True, validators=[validate_ldap_base_dn])

def delete(self, using=None, keep_parents=False):
from account_manager.models import LdapUser
from account_manager.models import LdapGroup
from _ldap import LDAPError
try:
ldap_users = LdapUser.get_users(self)
ldap_usernames = [user.username for user in ldap_users]
ldap_groups = LdapGroup.get_groups(self)
ldap_groupnames = [group.name for group in ldap_groups]
django_user = User.objects.filter(username__contains=ldap_usernames)
django_groups = Group.objects.filter(name__contains=ldap_groupnames)
django_user.delete()
django_groups.delete()
ldap_users.delete()
ldap_groups.delete()
except LDAPError:
# TODO: Save delete
pass
return super().delete(using, keep_parents)

def __str__(self):
return f'{self.name} - {self.ldap_base_dn}'
Expand Down
8 changes: 8 additions & 0 deletions backend/src/account_helper/validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import logging

logger = logging.getLogger(__name__)


def validate_ldap_base_dn(ldap_base_dn):
from account_manager.models import LdapUser
LdapUser.creation_test(ldap_base_dn)
File renamed without changes.
36 changes: 36 additions & 0 deletions backend/src/account_manager/api/v1/authentication/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.contrib.auth.models import User, Permission
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

import logging

logger = logging.getLogger(__name__)


class LamaTokenObtainPairSerializer(TokenObtainPairSerializer):

@classmethod
def get_token(cls, user: User):
token = super().get_token(user)

if user.is_superuser:
permissions = Permission.objects.all()
else:
permissions = user.user_permissions.all() | Permission.objects.filter(group__user=user)
perm_tuple = [LamaTokenObtainPairSerializer._get_casl_dict(x.codename, x.name) for x in permissions]

logger.error(Permission.objects.all())
logger.error(user.user_permissions.all())
# Add custom claims
token['user'] = {'username': user.username, 'email': user.email, 'rules': perm_tuple}
# ...

return token

@staticmethod
def _get_casl_dict(codename: str, description: str):
splitted_codename = codename.split('_')
subject = splitted_codename[-1]
subject = subject.capitalize()
action = "_".join(splitted_codename[0:-2]) if len(splitted_codename) > 2 else splitted_codename[0]

return {'action': action, 'subject': subject, 'description': description}
6 changes: 6 additions & 0 deletions backend/src/account_manager/api/v1/authentication/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .serializers import LamaTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView


class LamaTokenObtainPairView(TokenObtainPairView):
serializer_class = LamaTokenObtainPairSerializer
25 changes: 25 additions & 0 deletions backend/src/account_manager/api/v1/group/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import raise_errors_on_nested_writes

from account_helper.models import Realm
from account_manager.models import LdapGroup


class LdapGroupSerializer(serializers.ModelSerializer):
class Meta:
model = LdapGroup
fields = ('dn', 'name', 'description', 'members')
read_only_fields = ('dn',)
extra_kwargs = {'description': {'required': False}}

def create(self, validated_data):
realm_id = self.context["view"].kwargs.get("realm_id")
realms = Realm.objects.filter(id=realm_id)
if not realms.exists():
raise ValidationError(f"Realm with {realm_id} not found")
return LdapGroup.full_create(realms.first(), **validated_data)

def update(self, instance, validated_data):
raise_errors_on_nested_writes('update', self, validated_data)
return instance.full_update(instance, **validated_data)
Loading