diff --git a/core/authentication/api_v2.py b/core/authentication/api_v2.py
index 8026a9f..7935ae8 100644
--- a/core/authentication/api_v2.py
+++ b/core/authentication/api_v2.py
@@ -7,6 +7,7 @@ from django.contrib.auth import login
from django.urls import path
from django.dispatch import receiver
from django.db.models.signals import post_save
+from django.contrib.auth.models import Group
from knox.models import AuthToken
from knox.views import LoginView as KnoxLoginView
@@ -36,6 +37,26 @@ class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
+class GroupSerializer(serializers.ModelSerializer):
+ permissions = serializers.SerializerMethodField()
+ members = serializers.SerializerMethodField()
+
+ class Meta:
+ model = Group
+ fields = ('id', 'name', 'permissions', 'members')
+
+ def get_permissions(self, obj):
+ return ["*:" + p.codename for p in obj.permissions.all()]
+
+ def get_members(self, obj):
+ return [u.username for u in obj.user_set.all()]
+
+
+class GroupViewSet(viewsets.ModelViewSet):
+ queryset = Group.objects.all()
+ serializer_class = GroupSerializer
+
+
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def selfUser(request):
@@ -85,6 +106,7 @@ class LoginView(KnoxLoginView):
router = routers.SimpleRouter()
router.register(r'users', UserViewSet, basename='users')
+router.register(r'groups', GroupViewSet, basename='groups')
urlpatterns = router.urls + [
path('self/', selfUser),
diff --git a/core/authentication/tests/v2/test_users.py b/core/authentication/tests/v2/test_users.py
index 2011314..c60cbcc 100644
--- a/core/authentication/tests/v2/test_users.py
+++ b/core/authentication/tests/v2/test_users.py
@@ -132,3 +132,49 @@ class UserApiTest(TestCase):
content_type='application/json')
self.assertEqual(response.status_code, 200)
self.assertTrue('token' in response.json())
+
+
+class GroupApiTest(TestCase):
+
+ def setUp(self):
+ self.event = Event.objects.create(name='testevent', slug='testevent')
+ # Admin, Orga, Team, User are created by default
+ self.group1 = Group.objects.create(name='testgroup1')
+ self.group2 = Group.objects.create(name='testgroup2')
+ self.group1.permissions.add(Permission.objects.get(codename='add_item'))
+ self.group1.permissions.add(Permission.objects.get(codename='view_item'))
+ self.group2.permissions.add(Permission.objects.get(codename='view_event'))
+ self.group2.permissions.add(Permission.objects.get(codename='view_item'))
+ self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
+ self.user.user_permissions.add(Permission.objects.get(codename='add_event'))
+ self.user.groups.add(self.group1)
+ self.user.groups.add(self.group2)
+ self.user.save()
+ EventPermission.objects.create(event=self.event, user=self.user,
+ permission=Permission.objects.get(codename='delete_item'))
+ self.user.save()
+ self.token = AuthToken.objects.create(user=self.user)
+ self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
+
+ def test_groups(self):
+ response = self.client.get('/api/2/groups/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(response.json()), 6)
+ self.assertEqual(response.json()[0]['name'], 'Admin')
+ self.assertEqual(response.json()[1]['name'], 'Orga')
+ self.assertEqual(response.json()[2]['name'], 'Team')
+ self.assertEqual(response.json()[3]['name'], 'User')
+ self.assertEqual(response.json()[4]['name'], 'testgroup1')
+ self.assertEqual(response.json()[5]['name'], 'testgroup2')
+
+ def test_group(self):
+ response = self.client.get('/api/2/groups/5/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json()['name'], 'testgroup1')
+ permissions = response.json()['permissions']
+ self.assertEqual(len(permissions), 2)
+ self.assertTrue('*:add_item' in permissions)
+ self.assertTrue('*:view_item' in permissions)
+ members = response.json()['members']
+ self.assertEqual(len(members), 1)
+ self.assertEqual(members[0], 'testuser')
diff --git a/web/src/components/Navbar.vue b/web/src/components/Navbar.vue
index da5caca..3dfcc17 100644
--- a/web/src/components/Navbar.vue
+++ b/web/src/components/Navbar.vue
@@ -24,7 +24,7 @@
-
+
Admin
diff --git a/web/src/components/Table3D.vue b/web/src/components/Table3D.vue
new file mode 100644
index 0000000..dc0acc4
--- /dev/null
+++ b/web/src/components/Table3D.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+ {{ item[column] }} |
+
+
+ |
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/src/components/Timeline.vue b/web/src/components/Timeline.vue
index 71b8bd9..d56ae3f 100644
--- a/web/src/components/Timeline.vue
+++ b/web/src/components/Timeline.vue
@@ -25,8 +25,8 @@
-