# HG changeset patch # User ymh # Date 1501535918 -7200 # Node ID adad5563603c09835009df1d4d7c041fb6f45d4c # Parent 78246db1cbac5a40334eda5e9baa0f9ad70f3ac9 add personal group, default_group to users and add group info to session on backend diff -r 78246db1cbac -r adad5563603c src/irinotes/settings.py --- a/src/irinotes/settings.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/irinotes/settings.py Mon Jul 31 23:18:38 2017 +0200 @@ -197,11 +197,11 @@ 'level': LOG_LEVEL, 'propagate': True, }, - 'django.db.backends': { - 'handlers': ['file'], - 'level': LOG_LEVEL, - 'propagate': True, - }, + # 'django.db.backends': { + # 'handlers': ['file'], + # 'level': LOG_LEVEL, + # 'propagate': True, + # }, 'irinotes': { 'handlers': ['file'], 'level': LOG_LEVEL, diff -r 78246db1cbac -r adad5563603c src/notes/api/serializers/auth.py --- a/src/notes/api/serializers/auth.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/api/serializers/auth.py Mon Jul 31 23:18:38 2017 +0200 @@ -10,11 +10,12 @@ class GroupSerializer(serializers.ModelSerializer): owner = serializers.CharField(source='profile.owner.username', read_only=True) + is_personal = serializers.BooleanField(source='profile.is_personal', read_only=True) description = serializers.CharField(source='profile.description') class Meta: model = Group - fields = ['name', 'owner', 'description'] + fields = ['name', 'owner', 'is_personal', 'description'] class DetailGroupSerializer(GroupSerializer): @@ -27,7 +28,8 @@ class Meta: model = Group - fields = ['name', 'owner', 'description', 'users'] + fields = ['name', 'owner', 'description', 'users', 'is_personal'] + class WriteGroupSerializer(serializers.ModelSerializer): ''' diff -r 78246db1cbac -r adad5563603c src/notes/api/serializers/core.py --- a/src/notes/api/serializers/core.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/api/serializers/core.py Mon Jul 31 23:18:38 2017 +0200 @@ -3,8 +3,10 @@ """ import logging +from django.contrib.auth.models import Group +from rest_framework import serializers + from notes.models import Note, Session -from rest_framework import serializers logger = logging.getLogger(__name__) @@ -87,40 +89,63 @@ owner = serializers.SlugRelatedField( read_only=True, slug_field='username', default=serializers.CurrentUserDefault()) + group = serializers.SlugRelatedField(read_only=True, slug_field='name') class Meta: model = Session fields = ( 'ext_id', 'version', 'date', 'created', 'updated', - 'owner', 'title', 'description', 'protocol' + 'owner', 'title', 'description', 'protocol', 'group' ) - read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner') + read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner', 'group') class DetailSessionSerializer(serializers.ModelSerializer): owner = serializers.SlugRelatedField(read_only=True, slug_field='username') notes = DetailNoteSerializer(many=True, read_only=True) + group = serializers.SlugRelatedField(slug_field='name', read_only=True) + + class Meta: + model = Session + fields = ( + 'ext_id', 'version', 'date', 'created', 'updated', + 'owner', 'title', 'description', 'protocol', 'group', + 'notes' + ) + read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner', 'group') + +class CreateSessionSerializer(serializers.ModelSerializer): + + owner = serializers.SlugRelatedField( + read_only=True, slug_field='username', default=serializers.CurrentUserDefault()) + group = serializers.SlugRelatedField(slug_field='name', queryset=Group.objects.all(), required=False) class Meta: model = Session fields = ( 'ext_id', 'version', 'date', 'created', 'updated', - 'owner', 'title', 'description', 'protocol', - 'notes' - ) - read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner') - -class CreateSessionSerializer(serializers.ModelSerializer): - - owner = serializers.SlugRelatedField( - read_only=True, slug_field='username', default=serializers.CurrentUserDefault()) - - - class Meta: - model = Session - fields = ( - 'ext_id', 'version', 'date', 'created', 'updated', - 'owner', 'title', 'description', 'protocol' + 'owner', 'title', 'description', 'protocol', 'group' ) read_only_fields = ('version', 'created', 'updated', 'owner') + + def validate(self, data): + data = super().validate(data) + + group = data.get('group') + owner = data.get('owner') + + if group is None: + if owner and owner.profile and owner.profile.default_group: + group = owner.profile.default_group + if group is None and owner: + group = Group.objects.filter(profile__owner_personal=owner).first() + + if group is None: + raise serializers.ValidationError("group field is required or default group or personal group could not be found for owner") + elif not owner in group.user_set.all(): + raise serializers.ValidationError("Owner must be in group") + + data['group'] = group + return data + diff -r 78246db1cbac -r adad5563603c src/notes/locale/en/LC_MESSAGES/django.po --- a/src/notes/locale/en/LC_MESSAGES/django.po Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/locale/en/LC_MESSAGES/django.po Mon Jul 31 23:18:38 2017 +0200 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-21 10:51+0000\n" +"POT-Creation-Date: 2017-07-31 10:40+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,27 +16,31 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: models/auth.py:11 +#: models/auth.py:12 msgid "User" msgstr "User" -#: models/auth.py:12 +#: models/auth.py:13 msgid "Users" msgstr "Users" -#: models/auth.py:17 +#: models/auth.py:23 +msgid "UserProfile|default_group" +msgstr "default group" + +#: models/auth.py:26 msgid "UserProfile" msgstr "User profile" -#: models/auth.py:18 +#: models/auth.py:27 msgid "UserProfiles" msgstr "User profiles" -#: models/auth.py:25 +#: models/auth.py:48 msgid "GroupProfile" msgstr "Group profile" -#: models/auth.py:26 +#: models/auth.py:49 msgid "GroupProfiles" msgstr "Group profiles" @@ -96,66 +100,70 @@ msgid "Categories" msgstr "Categories" -#: models/core.py:17 +#: models/core.py:19 msgid "Session" msgstr "Session" -#: models/core.py:18 +#: models/core.py:20 msgid "Sessions" msgstr "Sessions" -#: models/core.py:20 +#: models/core.py:22 msgid "Session|date" msgstr "date" -#: models/core.py:29 +#: models/core.py:31 msgid "Session|title" msgstr "title" -#: models/core.py:34 +#: models/core.py:36 msgid "Session|description" msgstr "description" -#: models/core.py:39 +#: models/core.py:41 +msgid "Session|group" +msgstr "group" + +#: models/core.py:46 msgid "Session|protocol" msgstr "protocol" -#: models/core.py:48 +#: models/core.py:61 msgid "Note" msgstr "Note" -#: models/core.py:49 +#: models/core.py:62 msgid "Notes" msgstr "Notes" -#: models/core.py:52 +#: models/core.py:68 msgid "Note|tc_start" msgstr "start timecode" -#: models/core.py:53 +#: models/core.py:69 msgid "Note|tc_end" msgstr "end timeocde" -#: models/core.py:58 +#: models/core.py:74 msgid "Note|session" msgstr "session" -#: models/core.py:63 +#: models/core.py:79 msgid "Note|plain" msgstr "text plain" -#: models/core.py:68 +#: models/core.py:84 msgid "Note|html" msgstr "text html" -#: models/core.py:73 +#: models/core.py:89 msgid "Note|raw" msgstr "text raw" -#: models/core.py:78 +#: models/core.py:94 msgid "Note|margin_note" msgstr "margin note" -#: models/core.py:83 +#: models/core.py:99 msgid "Note|categorization" msgstr "categorization" diff -r 78246db1cbac -r adad5563603c src/notes/locale/fr/LC_MESSAGES/django.po --- a/src/notes/locale/fr/LC_MESSAGES/django.po Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/locale/fr/LC_MESSAGES/django.po Mon Jul 31 23:18:38 2017 +0200 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-21 10:51+0000\n" +"POT-Creation-Date: 2017-07-31 10:40+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,27 +17,31 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: models/auth.py:11 +#: models/auth.py:12 msgid "User" msgstr "Utilisateur" -#: models/auth.py:12 +#: models/auth.py:13 msgid "Users" msgstr "Utilisateurs" -#: models/auth.py:17 +#: models/auth.py:23 +msgid "UserProfile|default_group" +msgstr "Groupe par défaut" + +#: models/auth.py:26 msgid "UserProfile" msgstr "Profil utilisateur" -#: models/auth.py:18 +#: models/auth.py:27 msgid "UserProfiles" msgstr "Profils utilisateur" -#: models/auth.py:25 +#: models/auth.py:48 msgid "GroupProfile" msgstr "Profile groupe" -#: models/auth.py:26 +#: models/auth.py:49 msgid "GroupProfiles" msgstr "Profiles groupe" @@ -97,66 +101,70 @@ msgid "Categories" msgstr "Categories" -#: models/core.py:17 +#: models/core.py:19 msgid "Session" msgstr "Session" -#: models/core.py:18 +#: models/core.py:20 msgid "Sessions" msgstr "Sessions" -#: models/core.py:20 +#: models/core.py:22 msgid "Session|date" msgstr "date" -#: models/core.py:29 +#: models/core.py:31 msgid "Session|title" msgstr "titre" -#: models/core.py:34 +#: models/core.py:36 msgid "Session|description" msgstr "description" -#: models/core.py:39 +#: models/core.py:41 +msgid "Session|group" +msgstr "groupe" + +#: models/core.py:46 msgid "Session|protocol" msgstr "protocole" -#: models/core.py:48 +#: models/core.py:61 msgid "Note" msgstr "Note" -#: models/core.py:49 +#: models/core.py:62 msgid "Notes" msgstr "Notes" -#: models/core.py:52 +#: models/core.py:68 msgid "Note|tc_start" msgstr "timecode début" -#: models/core.py:53 +#: models/core.py:69 msgid "Note|tc_end" msgstr "timecode fin" -#: models/core.py:58 +#: models/core.py:74 msgid "Note|session" msgstr "session" -#: models/core.py:63 +#: models/core.py:79 msgid "Note|plain" msgstr "texte seul" -#: models/core.py:68 +#: models/core.py:84 msgid "Note|html" msgstr "texte html" -#: models/core.py:73 +#: models/core.py:89 msgid "Note|raw" msgstr "texte brut" -#: models/core.py:78 +#: models/core.py:94 msgid "Note|margin_note" msgstr "note de marge" -#: models/core.py:83 +#: models/core.py:99 msgid "Note|categorization" msgstr "catégorisation" diff -r 78246db1cbac -r adad5563603c src/notes/migrations/0001_initial.py --- a/src/notes/migrations/0001_initial.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/migrations/0001_initial.py Mon Jul 31 23:18:38 2017 +0200 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.2 on 2017-07-19 13:26 +# Generated by Django 1.11.2 on 2017-07-31 13:32 from __future__ import unicode_literals import colorful.fields @@ -68,6 +68,7 @@ ('description', models.TextField(blank=True, null=True)), ('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to='auth.Group')), ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('owner_personal', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='personal_group', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'GroupProfile', @@ -124,6 +125,7 @@ ('title', models.TextField(blank=True, null=True, verbose_name='Session|title')), ('description', models.TextField(blank=True, null=True, verbose_name='Session|description')), ('protocol', models.TextField(blank=True, null=True, verbose_name='Session|protocol')), + ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group', verbose_name='Session|group')), ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ @@ -135,7 +137,8 @@ name='UserProfile', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('default_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group', verbose_name='UserProfile|default_group')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'UserProfile', diff -r 78246db1cbac -r adad5563603c src/notes/models/auth.py --- a/src/notes/models/auth.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/models/auth.py Mon Jul 31 23:18:38 2017 +0200 @@ -7,13 +7,20 @@ class User(AbstractUser): + class Meta: verbose_name = _('User') verbose_name_plural = _('Users') class UserProfile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') + + # TODO: + default_group = models.ForeignKey( + Group, + null=False, + verbose_name=_("UserProfile|default_group")) class Meta: verbose_name = _('UserProfile') @@ -26,6 +33,17 @@ description = models.TextField(null=True, blank=True) # TODO: manage when user is deleted: put first user as owner. delete group if empty owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + # TODO: can not delete group when user is not deleted. + # TODO: other users cannot set as owner + # TODO: delete personal group when user is deleted + # TODO: change group name when user change name + # indicate that this group is a personal group. + # used this instead of a boolean because it allows to easily enforce that a user has only one personal group + owner_personal = models.OneToOneField(User, on_delete=models.CASCADE, null=True, related_name='personal_group') + + @property + def is_personal(self): + return self.owner == self.owner_personal class Meta: verbose_name = _('GroupProfile') diff -r 78246db1cbac -r adad5563603c src/notes/models/core.py --- a/src/notes/models/core.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/models/core.py Mon Jul 31 23:18:38 2017 +0200 @@ -3,6 +3,7 @@ """ from auditlog.registry import auditlog from django.conf import settings +from django.contrib.auth.models import Group from django.db import models from django.utils import timezone from django.utils.translation import ugettext_lazy as _ @@ -34,6 +35,11 @@ blank=True, verbose_name=_('Session|description') ) + group = models.ForeignKey( + Group, + null=False, + verbose_name=_('Session|group') + ) protocol = models.TextField( null=True, blank=True, diff -r 78246db1cbac -r adad5563603c src/notes/signals.py --- a/src/notes/signals.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/signals.py Mon Jul 31 23:18:38 2017 +0200 @@ -1,10 +1,17 @@ """ Signals for notes app """ +import logging + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group from django.db.models.signals import post_save from django.dispatch import receiver -from django.contrib.auth.models import Group -from notes.models import GroupProfile + +from notes.models import GroupProfile, UserProfile + +User = get_user_model() +logger = logging.getLogger(__name__) @receiver(post_save, sender=Group, dispatch_uid="group_created_signal") def group_saved_callback(sender, instance, **kwargs): @@ -13,3 +20,33 @@ profile = GroupProfile(group=instance) profile.save() +@receiver(post_save, sender=User, dispatch_uid="user_created_signal") +def user_saved_callback(sender, instance, **kwargs): + created = kwargs.pop('created') + if not instance: + return + base_group_name = instance.username + " group" + group_name = base_group_name + if created: + # create personal group + personal_group = None + personal_group_profile = GroupProfile.objects.filter(owner=instance, owner_personal=instance).first() + if personal_group_profile is None: + # find a new name + i = 1 + while Group.objects.filter(name=group_name).exists(): # should always ends... + group_name = "%s %s" % (base_group_name, i) + i += 1 + personal_group = Group.objects.create(name=group_name) + personal_group.user_set.add(instance) + personal_group_profile = personal_group.profile + personal_group_profile.description = "%s personal group" % instance.username + personal_group_profile.owner = instance + personal_group_profile.owner_personal = instance + personal_group_profile.save() + else: + personal_group = personal_group_profile.group + + UserProfile.objects.create(user=instance, default_group=personal_group) + # else we do nothing, because we do not know if the group's name was changed or not + # and we do not know the user older name diff -r 78246db1cbac -r adad5563603c src/notes/tests/api/auth.py --- a/src/notes/tests/api/auth.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/tests/api/auth.py Mon Jul 31 23:18:38 2017 +0200 @@ -20,12 +20,12 @@ User = get_user_model() self.user1 = User.objects.create_user( username='test_user1', - email='test_user@emial.com', + email='test_user@email.com', password='top_secret' ) self.user2 = User.objects.create_user( username='test_user2', - email='test_user@emial.com', + email='test_user@email.com', password='top_secret' ) @@ -58,14 +58,24 @@ self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(2, len(response.data), "Must have 2 groups") - for group_def in response.data: - self.assertIn('name', group_def.keys()) - self.assertIn('owner', group_def.keys()) - self.assertIn('description', group_def.keys()) + resp_json = response.json() + self.assertIn('count', resp_json) + self.assertIn('results', resp_json) + self.assertEqual(4, resp_json['count'], "Must have 4 groups") + self.assertEqual(4, len(resp_json['results']), "Must have 4 groups") + + for group_def in resp_json['results']: + self.assertIn('name', group_def) + self.assertIn('owner', group_def) + self.assertIn('is_personal', group_def) + self.assertIn('description', group_def) self.assertIn(group_def.get('owner'), ['test_user1', 'test_user2']) - self.assertIn(group_def.get('description'), ['This is the group 1', 'This is the group 2']) - self.assertIn(group_def.get('name'), ['group1', 'group2']) + self.assertIn(group_def.get('description'), [ + 'This is the group 1', + 'This is the group 2', + 'test_user1 personal group', + 'test_user2 personal group']) + self.assertIn(group_def.get('name'), ['group1', 'group2', 'test_user1 group', 'test_user2 group']) def test_create_group(self): url = reverse('auth_group-list') diff -r 78246db1cbac -r adad5563603c src/notes/tests/api/note.py --- a/src/notes/tests/api/note.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/tests/api/note.py Mon Jul 31 23:18:38 2017 +0200 @@ -43,6 +43,7 @@ title="a new session 1", description="Description 1", protocol="[]", + group=user1.profile.default_group, owner=user1 ) @@ -50,6 +51,7 @@ title="a new session 2", description="Description 2", protocol="[]", + group=user2.profile.default_group, owner=user2 ) @@ -57,6 +59,7 @@ title="a new session 3", description="Description 3", protocol="[]", + group=user3.profile.default_group, owner=user3 ) diff -r 78246db1cbac -r adad5563603c src/notes/tests/api/session.py --- a/src/notes/tests/api/session.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/tests/api/session.py Mon Jul 31 23:18:38 2017 +0200 @@ -6,12 +6,13 @@ from uuid import uuid4 from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group from django.urls import reverse from django.utils import timezone from rest_framework import status from rest_framework.test import APITransactionTestCase -from notes.models import Session, Note +from notes.models import Session, Note, GroupProfile logger = logging.getLogger(__name__) @@ -19,12 +20,12 @@ def setUp(self): User = get_user_model() - user1 = User.objects.create_user( + self.user1 = User.objects.create_user( username='test_user1', email='test_user@emial.com', password='top_secret' ) - user2 = User.objects.create_user( + self.user2 = User.objects.create_user( username='test_user2', email='test_user@emial.com', password='top_secret' @@ -35,24 +36,38 @@ password='top_secret' ) + self.group1 = Group(name='group1') + self.group1.save() + self.group1.user_set.add(self.user1) + self.group1.user_set.add(self.user2) + self.group1.profile.owner = self.user1 + self.group1.profile.description = "This is the group 1" + self.group1.profile.save() + + self.user2.profile.default_group = self.group1 + self.user2.profile.save() + self.session1 = Session.objects.create( title="a new session 1", description="Description 1", protocol="[]", - owner=user1 + group=self.user1.profile.default_group, + owner=self.user1 ) self.session2 = Session.objects.create( title="a new session 2", description="Description 2", protocol="[]", - owner=user2 + group=self.user2.profile.default_group, + owner=self.user2 ) self.session3 = Session.objects.create( title="a new session 3", description="Description 3", protocol="[]", + group=user3.profile.default_group, owner=user3 ) @@ -60,6 +75,7 @@ title="a new session 4", description="Description 4", protocol="[]", + group=user3.profile.default_group, owner=user3 ) @@ -150,14 +166,89 @@ response = self.client.post(url, { 'title': "a new session", 'description': "description of the session", - 'protocol': "[]" + 'protocol': "[]", + 'group': 'group1' }, format='json') - self.assertEqual(response.status_code, status.HTTP_201_CREATED) json = response.json() self.assertIn('ext_id', json) + session = Session.objects.get(ext_id=json['ext_id']) + self.assertIsNotNone(session) + self.assertEqual(self.group1, session.group) + + + def test_create_session_no_group(self): + url = reverse('notes:session-list') + self.client.login(username='test_user1', password='top_secret') + response = self.client.post(url, { + 'title': "a new session", + 'description': "description of the session", + 'protocol': "[]", + }, format='json') + + self.assertEqual(response.status_code, status.HTTP_201_CREATED, "Error when creating session %r" % response.json()) + json = response.json() + self.assertIn('ext_id', json) + + session = Session.objects.get(ext_id=json['ext_id']) + self.assertIsNotNone(session) + user1_personal_group = Group.objects.get(profile__owner_personal=self.user1) + self.assertEqual(user1_personal_group, session.group) + + def test_create_session_no_group_default(self): + url = reverse('notes:session-list') + self.client.login(username='test_user2', password='top_secret') + response = self.client.post(url, { + 'title': "a new session", + 'description': "description of the session", + 'protocol': "[]", + }, format='json') + + self.assertEqual(response.status_code, status.HTTP_201_CREATED, "Error when creating session %r" % response.json()) + json = response.json() + self.assertIn('ext_id', json) + + session = Session.objects.get(ext_id=json['ext_id']) + self.assertIsNotNone(session) + self.assertEqual(self.group1, session.group) + + + def test_create_session_no_group_default(self): + url = reverse('notes:session-list') + self.client.login(username='test_user2', password='top_secret') + response = self.client.post(url, { + 'title': "a new session", + 'description': "description of the session", + 'protocol': "[]", + }, format='json') + + self.assertEqual(response.status_code, status.HTTP_201_CREATED, "Error when creating session %r" % response.json()) + json = response.json() + self.assertIn('ext_id', json) + + session = Session.objects.get(ext_id=json['ext_id']) + self.assertIsNotNone(session) + self.assertEqual(self.group1, session.group) + + + def test_create_session_bad_group(self): + url = reverse('notes:session-list') + self.client.login(username='test_user3', password='top_secret') + response = self.client.post(url, { + 'title': "a new session", + 'description': "description of the session", + 'protocol': "[]", + 'group': "group1" + }, format='json') + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + json = response.json() + self.assertIn('non_field_errors', json) + self.assertIn('Owner must be in group', json['non_field_errors']) + + def test_create_session_with_ext_id(self): url = reverse('notes:session-list') self.client.login(username='test_user1', password='top_secret') @@ -166,6 +257,7 @@ 'ext_id': ext_id, 'title': "a new session", 'description': "description of the session", + 'group': 'group1', 'protocol': "[]" }, format='json') diff -r 78246db1cbac -r adad5563603c src/notes/tests/models/auth.py --- a/src/notes/tests/models/auth.py Sun Jul 30 01:02:09 2017 +0200 +++ b/src/notes/tests/models/auth.py Mon Jul 31 23:18:38 2017 +0200 @@ -20,6 +20,10 @@ email='test_user@emial.com', password='top_secret' ) + + group = Group(name='test_user2 group') + group.save() + self.user2 = User.objects.create_user( username='test_user2', email='test_user@emial.com', @@ -32,3 +36,23 @@ self.assertIsNotNone(self.group) self.assertIsNotNone(self.group.profile) + def test_create_personal_group(self): + self.assertIsNotNone(self.user1.profile) + self.assertIsNotNone(self.user2.profile) + default_group1 = self.user1.profile.default_group + self.assertIsNotNone(default_group1) + self.assertIsNotNone(default_group1.profile) + self.assertTrue(default_group1.profile.is_personal) + self.assertEqual(default_group1.profile.owner, self.user1) + self.assertEqual(default_group1.profile.owner_personal, self.user1) + + def test_create_personal_group_new_name(self): + default_group2 = self.user2.profile.default_group + self.assertIsNotNone(default_group2) + self.assertEqual(default_group2.name, "test_user2 group 1") + + def test_create_personal_group(self): + personal_group = Group.objects.get(profile__owner_personal=self.user1) + self.assertIsNotNone(personal_group) + self.assertIn(self.user1, personal_group.user_set.all()) + diff -r 78246db1cbac -r adad5563603c src/requirements/dev.txt --- a/src/requirements/dev.txt Sun Jul 30 01:02:09 2017 +0200 +++ b/src/requirements/dev.txt Mon Jul 31 23:18:38 2017 +0200 @@ -1,1 +1,3 @@ -r base.txt +pylint-django +pylint