Add share snapshot mutation, including unit tests

This commit is contained in:
Ramon Wenger 2021-05-08 23:19:58 +02:00
parent 631bfb338a
commit 4bdcdd8774
6 changed files with 121 additions and 4 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.22 on 2021-05-08 20:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('books', '0027_auto_20210429_1444'),
]
operations = [
migrations.AddField(
model_name='snapshot',
name='shared',
field=models.BooleanField(default=False),
),
]

View File

@ -71,6 +71,7 @@ class Snapshot(models.Model):
)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, null=True)
shared = models.BooleanField(default=False)
objects = SnapshotManager()

View File

@ -1,7 +1,7 @@
from books.schema.mutations.chapter import UpdateChapterVisibility
from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, SyncModuleVisibility
from books.schema.mutations.snapshot import CreateSnapshot, ApplySnapshot
from books.schema.mutations.snapshot import CreateSnapshot, ApplySnapshot, ShareSnapshot
from books.schema.mutations.topic import UpdateLastTopic
@ -16,3 +16,4 @@ class BookMutations(object):
sync_module_visibility = SyncModuleVisibility.Field()
create_snapshot = CreateSnapshot.Field()
apply_snapshot = ApplySnapshot.Field()
share_snapshot = ShareSnapshot.Field()

View File

@ -45,7 +45,7 @@ class ApplySnapshot(relay.ClientIDMutation):
user = info.context.user
selected_class_id = args.get('selected_class')
selected_class = get_object(SchoolClass, selected_class_id)
#reset everything
# reset everything
for chapter in Chapter.get_by_parent(snapshot.module):
cb_qs = ContentBlock.get_by_parent(chapter)
without_owner = Q(owner__isnull=True)
@ -55,7 +55,7 @@ class ApplySnapshot(relay.ClientIDMutation):
cb.hidden_for.remove(selected_class)
for cb in cb_qs.filter(owner_user):
cb.visible_for.remove(selected_class)
#apply snapshot
# apply snapshot
if not selected_class.users.filter(username=user.username).exists() or not user.is_teacher():
raise PermissionError('Not allowed')
for content_block in snapshot.hidden_content_blocks.all():
@ -69,3 +69,24 @@ class ApplySnapshot(relay.ClientIDMutation):
if chapter_snapshot.description_hidden:
chapter.description_hidden_for.add(selected_class)
return cls(success=True, module=snapshot.module)
class ShareSnapshot(relay.ClientIDMutation):
class Input:
snapshot = graphene.ID(required=True)
shared = graphene.Boolean(required=True)
success = graphene.Boolean(required=True)
snapshot = graphene.Field(SnapshotNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **args):
snapshot_id = args.get('snapshot')
shared = args.get('shared')
user = info.context.user
snapshot = get_object(Snapshot, snapshot_id)
if snapshot.creator != user:
raise PermissionError('Not permitted')
snapshot.shared = shared
snapshot.save()
return cls(success=True, snapshot=snapshot)

View File

@ -86,7 +86,7 @@ class ModuleNode(DjangoObjectType):
@staticmethod
def resolve_snapshots(parent, info, **kwargs):
return parent.snapshots.all()
return parent.snapshots.filter(creator=info.context.user)
class RecentModuleNode(DjangoObjectType):

View File

@ -85,6 +85,32 @@ query SnapshotDetail($id: ID!) {
}
"""
SHARE_SNAPSHOT_MUTATION = """
mutation ShareSnapshot($input: ShareSnapshotInput!) {
shareSnapshot(input: $input) {
success
snapshot {
shared
}
}
}
"""
MODULE_SNAPSHOTS_QUERY = """
query SnapshotQuery($slug: String!) {
module(slug: $slug) {
snapshots {
id
title
created
creator {
username
}
}
}
}
"""
def edges_to_array(entity):
return [edge['node'] for edge in entity.get('edges')]
@ -263,3 +289,53 @@ class CreateSnapshotTestCase(SkillboxTestCase):
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb1['hiddenFor']])
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb2['hiddenFor']])
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb3['visibleFor']])
class SnapshotTestCase(SkillboxTestCase):
def setUp(self) -> None:
self.createDefault()
self.client = self.get_client()
self.slug = 'some-module'
self.teacher2 = User.objects.get(username='teacher2')
self.module = ModuleFactory(slug=self.slug)
self.skillbox_class = SchoolClass.objects.get(name='skillbox')
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
user=self.teacher)
Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
user=self.teacher2)
def test_show_only_own_snapshots(self):
result = self.client.execute(MODULE_SNAPSHOTS_QUERY, variables={
"slug": self.slug
})
self.assertIsNone(result.get('errors'))
snapshots = result['data']['module']['snapshots']
self.assertEqual(len(snapshots), 1)
self.assertEqual(snapshots[0]['creator']['username'], 'teacher')
def test_share_snapshot(self):
self.assertFalse(self.snapshot.shared)
result = self.client.execute(SHARE_SNAPSHOT_MUTATION, variables={
'input': {
'snapshot': to_global_id('Snapshot', self.snapshot.id),
'shared': True
}
})
self.assertIsNone(result.get('errors'))
data = result['data']['shareSnapshot']
self.assertTrue(data['success'])
self.assertTrue(data['snapshot']['shared'])
snapshot = Snapshot.objects.get(pk=self.snapshot.pk)
self.assertTrue(snapshot.shared)
def test_dont_share_foreign_snapshot(self):
self.assertFalse(self.snapshot.shared)
teacher2_client = self.get_client(self.teacher2)
result = teacher2_client.execute(SHARE_SNAPSHOT_MUTATION, variables={
'input': {
'snapshot': to_global_id('Snapshot', self.snapshot.id),
'shared': True
}
})
self.assertIsNotNone(result.get('errors'))