diff --git a/Pipfile b/Pipfile index a24b04d0..63c23cba 100644 --- a/Pipfile +++ b/Pipfile @@ -30,3 +30,4 @@ django-storages = "*" boto3 = "*" django-compressor = "*" django-libsass = "*" +bleach = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 7d354839..0dea226a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0313ae3eba93a9c5712508539682881c11aeec5f240c2ba8832498f36d99a5b0" + "sha256": "a9b9215ef6546bd1d78142e5a1918cb4ba623ff8dd878db3761baa0866c39527" }, "pipfile-spec": 6, "requires": { @@ -31,20 +31,28 @@ ], "version": "==4.6.0" }, - "boto3": { + "bleach": { "hashes": [ - "sha256:03067dc8ac0b16cf7ef1e016a08135c82a75e330bdbddea970e4c60ea9e4f699", - "sha256:061595d40ea97e4aae8beb9a2eebfe7b1851f40c3c779529d43ad4f8abe5b3d7" + "sha256:0ee95f6167129859c5dce9b1ca291ebdb5d8cd7e382ca0e237dfd0dad63f63d8", + "sha256:24754b9a7d530bf30ce7cbc805bc6cce785660b4a10ff3a43633728438c105ab" ], "index": "pypi", - "version": "==1.8.6" + "version": "==2.1.4" + }, + "boto3": { + "hashes": [ + "sha256:3937eaba7cc429d1593824397f1d7dda4c9565c1269e8d3f665cee3c1b1b955c", + "sha256:ae1bc72a3921807ef8c0daa6c4bd147e6caa630df263e5ea5e8c36535e17ee73" + ], + "index": "pypi", + "version": "==1.8.9" }, "botocore": { "hashes": [ - "sha256:bd85f6491207b632c76fc6ca3e74b5d75a48c7f06f68ae5e98e794e6be10bc06", - "sha256:dc28453285802c1a2db0be8085e99631394fd1e833265d53a4071ef8c7c2415a" + "sha256:1294d1422b278dac28869d5b96156171dd8d5b609da28fec006add8a81a31dfa", + "sha256:91c32b97dd2f1046b1de3ce5c8bc19cf4993bc631864c9fcbf51f261bc3a7aab" ], - "version": "==1.11.6" + "version": "==1.11.9" }, "certifi": { "hashes": [ @@ -136,11 +144,11 @@ }, "django-storages": { "hashes": [ - "sha256:9e0f3423cdf8fabe74c174380de6cd65b9343b5c83c08f35ace57213f17fb083", - "sha256:e021ae94c0ca39c683260fa0065cae0df041d795dd79fee8f7bf4ba31798640d" + "sha256:8e35d2c7baeda5dc6f0b4f9a0fc142d25f9a1bf72b8cebfcbc5db4863abc552d", + "sha256:b1a63cd5ea286ee5a9fb45de6c3c5c0ae132d58308d06f1ce9865cfcd5e470a7" ], "index": "pypi", - "version": "==1.7" + "version": "==1.7.1" }, "django-taggit": { "hashes": [ @@ -160,6 +168,7 @@ "sha256:b6714c3e4b0f8d524f193c91ecf5f5450092c2145439ac2769711f7eba89a9d9", "sha256:c375e4f95a3a64fccac412e36fb42ba36881e52313ec021ef410b40f67cddca4" ], + "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*'", "version": "==3.8.2" }, "docutils": { @@ -282,30 +291,19 @@ "sha256:0013f590a8f260df60bcfd65db19d18efc04e7f046c3c82a40e2e2b3292a937c", "sha256:0b899ee80920bb533f26581af9b4660bc12aff4562555afe74e429101ebf3c94", "sha256:12f29d6c23424f704c66b5b68c02fe0b571504459605cfe36ab8158359b0e1bb", - "sha256:135e9aa65150c53f7db85bf2bebb8a0e1a48ea850e80cf66e16dd04fa09d309c", "sha256:153ec6f18f7b61641e0e6e502acfaf4a06c9aba2ea11c0b4b3578ea9f13a4a4a", - "sha256:17fe25efc785194d48c38fad85dce470013ba19d2fb66639e149f14bccf1327f", "sha256:1912b7230459fd53682dae32b83cbd8e5d642ba36d4be18566f00a9c063aa13d", "sha256:1a5b93084e01328a1cb1ecdad99d11d75e881e89a95f88d85b523646553b36c2", "sha256:25193f934d37d836a6b1f4c062ce574a96cbca7c6d9dc8ddfbbac7f9c54deaa4", - "sha256:2c042352b430d678db50c78c5214e19638eff8b688941271da2de21fd298dfe5", - "sha256:2e818dbe445e86fc6c266973fe540c35125c42eb2cf13a6095e9adaa89c0deb5", "sha256:2fcde9954c8882d1c7f93bb828caa34a4c5e3ee69dbc7895dc8652ad972b455a", "sha256:35f7d998b8e82fb3fb51ff88b30485eb81cd7dd56ec7e1a8deba23eb88532d44", - "sha256:37cc0339abfa9e295c75d9a7f227d35cb44716feb95057f9449c4a9e9a17daf7", "sha256:43334f9581cd067945b8898cef9eb5714ee4883f8de0304c011f1dbdb1d4e2aa", "sha256:4bd4a71501b6d51db4abc07e1f43f5a6fed0a1a9583cca0b401d6af50284b0db", - "sha256:57aa6198ba8acba1313c3b743e267d821a60cac77e6026caf0b55ca58d3d23be", "sha256:5b0d657460d9f3615876fec6306e97ca15a471f6169b622d76a47e270998acf1", - "sha256:5cd36804f9f06a914a883fe682df5711d16d7b4f44d43189c5f013e7cd91e149", "sha256:6977cf073d83358b34f93abf5c1f1193b88675fe0e4441e0e28318bc3dcba7a0", "sha256:718ec7a122b28d64afc5fbc3a9b99bb0545ef511373cac06fe7624520e82cb20", - "sha256:7dfbefdb3fb911ca9faed307bf309861e9995e36cca6b761c7ba6d9b77a9744a", "sha256:801cca8923508311bf5d6d0f7da5362552e8208ebd8ec0d7b9f2cd2ff5705734", - "sha256:82b172e3264e62372c01b5b009b5b1a02fbb9276cbe5cc57ab00a6d6e5ed9a18", - "sha256:82d1ff571489765df2816785d532e243bde213752156c227fca595723ec5ff42", "sha256:8580fc58074a16b749905b26cf8363f7b628dd167ba0130f5382cdc91c86b509", - "sha256:931030d1d6282b7900e6b0a7ff9ecdb503b5e1e6781800dab2b71a9f39405bff", "sha256:9525cd680a6f9e80c6c0af03cf973e6505c59f60b4745f682cd1a449e54b31bb", "sha256:a224651a81e45ef4f1d0164e256c5f6b4abb49f2ae8f22ba2f3a9d0ff338e608", "sha256:a370d1c570f1d72e877099651e752332444b1c5009381f043c9da5fd47f3ebae", @@ -314,12 +312,7 @@ "sha256:b85f703c2ffe539313e39ce0676bed0f355cec45a16e58c9ab7417445843047c", "sha256:b9f63451084a718eccdeb1e382768c94647915653af4d6019f64560d9e98642b", "sha256:c793dfaa130847ccff958492b76ae8b9304e60b8a79a92962cb19e368276a22b", - "sha256:d60c1625b108432ace8b1fa1a584017e5efa73f107d0f493c7f39c79bebf1d41", - "sha256:dc4b018d5c9b636f7546583c5591b9ea00c328c3e5871992ef5b95bac353f097", - "sha256:ddd16ab250b4fc97db1c47407e78c25216a75c29d29d10ad37e51b7a2ec7b2c3", - "sha256:e126ff4fed71e78333840c07279e1617f63cfca76d63ad5b27d65a7277206a3d", - "sha256:f8d49be8c282df8d2e1ab6ab53ab8abd859b1fa6fed384457ee85c9eff64ef97", - "sha256:fcf64c91fd44485100a2965d23bb0e227d093e91f7e776c5ca3b32574766eb56" + "sha256:ddd16ab250b4fc97db1c47407e78c25216a75c29d29d10ad37e51b7a2ec7b2c3" ], "index": "pypi", "version": "==5.0.0" @@ -410,6 +403,7 @@ "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" ], + "markers": "python_version != '3.3.*' and python_version < '4' and python_version != '3.2.*' and python_version != '3.1.*' and python_version >= '2.6' and python_version != '3.0.*'", "version": "==2.19.1" }, "rjsmin": { @@ -473,6 +467,7 @@ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], + "markers": "python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version < '4' and python_version >= '2.6' and python_version != '3.2.*'", "version": "==1.23" }, "wagtail": { @@ -485,7 +480,7 @@ }, "wagtail-factories": { "git": "https://github.com/mvantellingen/wagtail-factories.git", - "ref": "master" + "ref": "1ead51cadaad3b4530ba2197ccf45d2dca87dbdf" }, "webencodings": { "hashes": [ @@ -511,21 +506,13 @@ } }, "develop": { - "appnope": { - "hashes": [ - "sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0", - "sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71" - ], - "markers": "sys_platform == 'darwin'", - "version": "==0.1.0" - }, "awscli": { "hashes": [ - "sha256:5929010baf1dcaa443465906020df7a8b813390c04811eab29f85a48125f5e65", - "sha256:e6a55a8c41fa3c9fed8e3884126d1fa477a478eac5192befa464de12a267a33c" + "sha256:ef7145fe16d4995121868237dc30051dc9238af6211f9dc57cfb1937ea962990", + "sha256:f953de87b96fc9d237603146c34b0b979ebc31e0f2eb43ce77deb7ab563b47dd" ], "index": "pypi", - "version": "==1.16.6" + "version": "==1.16.9" }, "backcall": { "hashes": [ @@ -536,10 +523,10 @@ }, "botocore": { "hashes": [ - "sha256:bd85f6491207b632c76fc6ca3e74b5d75a48c7f06f68ae5e98e794e6be10bc06", - "sha256:dc28453285802c1a2db0be8085e99631394fd1e833265d53a4071ef8c7c2415a" + "sha256:1294d1422b278dac28869d5b96156171dd8d5b609da28fec006add8a81a31dfa", + "sha256:91c32b97dd2f1046b1de3ce5c8bc19cf4993bc631864c9fcbf51f261bc3a7aab" ], - "version": "==1.11.6" + "version": "==1.11.9" }, "colorama": { "hashes": [ @@ -637,18 +624,7 @@ }, "pyasn1": { "hashes": [ - "sha256:0ad0fe0593dde1e599cac0bf65bb1a4ec663032f0bc68ee44850db4251e8c501", - "sha256:13794d835643ee970b2c059dbfe4eb5d751e16c693c8baee61c526abd209e5c7", - "sha256:49a8ed515f26913049113820b462f698e6ed26df62c389dafb6fa3685ddca8de", - "sha256:74ac8521a0480f228549be20bea555ae35678f0e754c2fbc6f1576b0959bec43", - "sha256:89399ca8ecd4524f974e926d4ef9e7a787903e01f0a9cdff3131ad1361792fe5", - "sha256:8f291e0338d519a1a0d07f0b9d03c9265f6be26eb32fdd21af6d3259d14ea49c", "sha256:b9d3abc5031e61927c82d4d96c1cec1e55676c1a991623cfed28faea73cdd7ca", - "sha256:d3bbd726c1a760d4ca596a4d450c380b81737612fe0182f5bb3caebc17461fd9", - "sha256:dea873d6c907c1cf1341fd88742a61efce33227d7743cb37564ab7d7e77dd9fd", - "sha256:ded5eea5cb88bc1ce9aa074b5a3092f95ce4741887e317e9b49c7ece75d7ea0e", - "sha256:e8b69ea2200d42201cbedd486eedb8980f320d4534f83ce2fb468e96aa5545d0", - "sha256:edad117649643230493aeb4955456ce19ab4b12e94489dde6f7094cdb5a3c87e", "sha256:f58f2a3d12fd754aa123e9fa74fb7345333000a035f3921dbdaa08597aa53137" ], "version": "==0.4.4" @@ -723,6 +699,7 @@ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], + "markers": "python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version < '4' and python_version >= '2.6' and python_version != '3.2.*'", "version": "==1.23" }, "wcwidth": { diff --git a/server/book/schema/inputs.py b/server/book/schema/inputs.py index 332ecd94..3c5c38db 100644 --- a/server/book/schema/inputs.py +++ b/server/book/schema/inputs.py @@ -4,11 +4,13 @@ import graphene class InputTypes(graphene.Enum): text_block = 'text_block' - basic_knowledge = 'basic_knowledge' + # basic_knowledge = 'basic_knowledge' # probably won't be using this over the API student_entry = 'student_entry' image_block = 'image_block' link_block = 'link_block' task = 'task' + video_block = 'video_block' + document_block = 'document_block' class ContentElementInput(InputObjectType): @@ -25,5 +27,4 @@ class ContentElementInput(InputObjectType): class ContentBlockInput(InputObjectType): title = graphene.String(required=True) type = graphene.String() - after = graphene.ID() contents = graphene.List(ContentElementInput) diff --git a/server/book/schema/mutations.py b/server/book/schema/mutations.py index 2e01e84a..dd7cc7bb 100644 --- a/server/book/schema/mutations.py +++ b/server/book/schema/mutations.py @@ -1,9 +1,9 @@ import json +import bleach import graphene from graphene import relay from django.core.exceptions import ValidationError -from wagtail.core.fields import StreamField from api.utils import get_object, get_errors from book.models import ContentBlock, Chapter @@ -11,6 +11,32 @@ from book.schema.inputs import ContentBlockInput from book.schema.queries import ContentBlockNode +def handle_content_blocks(content_data): + new_contents = [] + for content in content_data: + # todo: add all the content blocks + # todo: sanitize user inputs! + if content['type'] == 'text_block': + new_contents.append({ + 'type': 'text_block', + 'value': { + 'text': '
{}
'.format(bleach.clean(content['text'])) + }}) + elif content['type'] == 'student_entry': + pass + elif content['type'] == 'image_block': + pass + elif content['type'] == 'link_block': + pass + elif content['type'] == 'task': + pass + elif content['type'] == 'video_block': + pass + elif content['type'] == 'document_block': + pass + return new_contents + + class MutateContentBlock(relay.ClientIDMutation): class Input: id = graphene.ID() @@ -63,9 +89,14 @@ class MutateContentBlock(relay.ClientIDMutation): return cls(content_block=None, errors=errors) +# todo: handle mutation for add and for edit (with the ID of the content block instead of a sibling) +# todo: merge with above class, for error handling and sibling assignment class AddContentBlock(relay.ClientIDMutation): class Input: content_block = graphene.Argument(ContentBlockInput) + # todo: handle both of these differently, one for a new chapter maybe + parent = graphene.ID() + after = graphene.ID() new_content_block = graphene.Field(ContentBlockNode) @@ -74,22 +105,14 @@ class AddContentBlock(relay.ClientIDMutation): content_block_data = args.get('content_block') title = content_block_data.get('title') new_content_block = ContentBlock(title=title) - parent = Chapter.objects.get(pk=18).specific # atm just "1.1 Lehrbeginn" / todo: dynamic, refactor in above class + parent = Chapter.objects.get( + pk=18).specific # atm just "1.1 Lehrbeginn" / todo: dynamic, refactor in above class parent.add_child(instance=new_content_block) revision = new_content_block.save_revision() revision.publish() - new_content_block.save() - contents = content_block_data.get('contents') - for content in contents: - # todo: add all the content blocks - # todo: refactor this mess - if content['type'] == 'text_block': - new_content_block.contents = json.dumps([ - {'type': 'text_block', 'value': { - 'text': '{}
'.format(content['text']) - }} - ]) + new_contents = handle_content_blocks(contents) + new_content_block.contents = json.dumps(new_contents) new_content_block.save() return cls(new_content_block=new_content_block)