From f526ed51665a9955a7dac26878b16d07e7aeb758 Mon Sep 17 00:00:00 2001 From: Scot Hacker Date: Thu, 20 Dec 2018 17:08:09 -0800 Subject: [PATCH] Strip unwanted tags from task note and comments --- Pipfile | 3 + Pipfile.lock | 309 ++++++++++++++++++++++++++++----------- README.md | 3 + todo/__init__.py | 2 +- todo/models.py | 2 +- todo/tests/test_views.py | 63 +++++++- todo/views.py | 8 +- 7 files changed, 298 insertions(+), 92 deletions(-) diff --git a/Pipfile b/Pipfile index b0e6883..bc89ff6 100644 --- a/Pipfile +++ b/Pipfile @@ -12,8 +12,11 @@ pytest-django = "*" "flake8" = "*" factory-boy = "*" titlecase = "*" +bleach = "*" [dev-packages] +pylint = "*" +mypy = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index f43c48c..18e8d8e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8aa62fe5923a75a6df757c643dbd98177e66bd0bc9e429d65006f042f73f5a32" + "sha256": "77ef40c5c921d99d1a0826dca9dd8328afcf0d75031cbf01d65b581c6c4fbe57" }, "pipfile-spec": 6, "requires": { @@ -16,51 +16,66 @@ ] }, "default": { + "atomicwrites": { + "hashes": [ + "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", + "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" + ], + "version": "==1.2.1" + }, "attrs": { "hashes": [ - "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9", - "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450" + "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", + "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" ], - "version": "==17.4.0" + "version": "==18.2.0" + }, + "bleach": { + "hashes": [ + "sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718", + "sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9" + ], + "index": "pypi", + "version": "==3.0.2" }, "django": { "hashes": [ - "sha256:2d8b9eed8815f172a8e898678ae4289a5e9176bc08295676eff4228dd638ea61", - "sha256:d81a1652963c81488e709729a80b510394050e312f386037f26b54912a3a10d0" + "sha256:068d51054083d06ceb32ce02b7203f1854256047a0d58682677dd4f81bceabd7", + "sha256:55409a056b27e6d1246f19ede41c6c610e4cab549c005b62cbeefabc6433356b" ], "index": "pypi", - "version": "==2.0.4" + "version": "==2.1.4" }, "django-extensions": { "hashes": [ - "sha256:37a543af370ee3b0721ff50442d33c357dd083e6ea06c5b94a199283b6f9e361", - "sha256:bc9f2946c117bb2f49e5e0633eba783787790ae810ea112fe7fd82fa64de2ff1" + "sha256:8317a3fe479b1ba3e3a04ecf33fb8d6ccf09bb18f30eab64e34c40a593741d26", + "sha256:a76a61566f1c8d96acc7bcf765080b8e91367a25a2c6f8c5bddd574493839180" ], "index": "pypi", - "version": "==2.0.6" + "version": "==2.1.4" }, "factory-boy": { "hashes": [ - "sha256:bd5a096d0f102d79b6c78cef1c8c0b650f2e1a3ecba351c735c6d2df8dabd29c", - "sha256:be2abc8092294e4097935a29b4e37f5b9ed3e4205e2e32df215c0315b625995e" + "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", + "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" ], "index": "pypi", - "version": "==2.10.0" + "version": "==2.11.1" }, "faker": { "hashes": [ - "sha256:9cc12b821f32ff45f6edfdc1ab7be3893b60b1224e952d68322a57e5b26a4a15", - "sha256:b06d0dc0166618298e668ced513ced7b10df34f3ad2045f22f1d7d88704e8e9c" + "sha256:228419b0a788a7ac867ebfafdd438461559ab1a0975edb607300852d9acaa78d", + "sha256:52a3dcc6a565b15fe1c95090321756d5a8a7c1caf5ab3df2f573ed70936ff518" ], - "version": "==0.8.12" + "version": "==1.0.1" }, "flake8": { "hashes": [ - "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", - "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" + "sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670", + "sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2" ], "index": "pypi", - "version": "==3.5.0" + "version": "==3.6.0" }, "mccabe": { "hashes": [ @@ -71,115 +86,112 @@ }, "more-itertools": { "hashes": [ - "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", - "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", - "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", + "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", + "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" ], - "version": "==4.1.0" + "version": "==4.3.0" }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff" + "sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095", + "sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f" ], - "version": "==0.6.0" + "version": "==0.8.0" }, "psycopg2-binary": { "hashes": [ - "sha256:02eb674e3d5810e19b4d5d00720b17130e182da1ba259dda608aaf33d787347d", - "sha256:3a14baeabcebd4662f12f4bff03e0574a2369a2e41baf829e6fb4a24c95cf88b", - "sha256:436a503eda41f6adb08f292f40a3784fce0a5f351b6ae7b19a911904db53af93", - "sha256:465ff1d427ed42c31e456dbbd9edab3552be18a0edaef7450c5b3e6fee745052", - "sha256:4a1a5ea2fa4b53191637b162873a82822d92a85a08beefe28296b8eb5cf2fea5", - "sha256:4a4f23a08fbccbe40ecdb5384d807bcb469ea71dd87e6be2e80b036b8e6d47df", - "sha256:77a2fc622a1f2d08a707673c9be5769d521f03d867d305f172bb417fa7882754", - "sha256:8014c06a9ed7b78ba81beff3ae71acd78c212390f8ed839e9ce22735880bd5b4", - "sha256:83af04029bcb4b56c852e5876fef71340dcb465fa44fc99f80bac72e10fb0b74", - "sha256:86c0d2587f56776f25d52cca8e275adf495c8e01933fbfc2ca23b124610ab761", - "sha256:9305d7cbc802aaefac5c75a3df725f2654797369f32b18d4d0adb382dfab6c09", - "sha256:9b5ddbed85ec73293695d7116589d956ef0dd3fcf7bf3b2a3bc1e8e54c1d543a", - "sha256:a3d2cc0cb0b988dbfd0d11f7fac34058b25a6ce533ed5b8e88d6cb315e77d54a", - "sha256:ab1db8f3e96570d9f7ebc45133ce2574804b2280499baade178e163d022107b5", - "sha256:b039f51bca1ddd70234cc3f84f94f42ad43861b931bdfb497f887c60c39a6565", - "sha256:b287ddf4cafcfb632974907d1e7862119e36bb758228bdb07dd247553e4cdfc0", - "sha256:b6b2b26590304d97ef2af28d153ee99ace6fe0806934f4618edfc87216c77f91", - "sha256:c4c6004d410c77bfa5389ae9485498ce32805447a67afbfe8db0d247a5c88fa1", - "sha256:c606bff0978ee4858d86d40f6b6ab0c4cac4474f627bd054683dc03a4fc1a366", - "sha256:c8220c521a408b41c4f14036004a621ed0d965941286b978cd2ea2623fabd755", - "sha256:cb07184a4bfad304831f0a88b1c13fbd8cf9fcdf1f11e71c477dd6d7b1b078a0", - "sha256:cf3911fba0c47fc1313b5783183cda301032b14637a0b7a336766ae46998c7ee", - "sha256:d0972f062c73956332e9681dfdb133168618f0abfecc96e89f0205ac89cd454b", - "sha256:d1dd3eb8edd354083f5d27b968c5a17854c41347ba5a480b520be85ec1a8495c", - "sha256:d51c7ed810fce1e50464088c37cc8da05534de8afb12a732500827ebcc480081", - "sha256:d8940b5104588d6313315e037f0f5ed68d2e5f62ccc1c429d3cff11d2ba6de3f", - "sha256:de4f88f823037a71ea5ef3c1041d96b8a68d73343133edda684fd42f575bd9d7" + "sha256:036bcb198a7cc4ce0fe43344f8c2c9a8155aefa411633f426c8c6ed58a6c0426", + "sha256:1d770fcc02cdf628aebac7404d56b28a7e9ebec8cfc0e63260bd54d6edfa16d4", + "sha256:1fdc6f369dcf229de6c873522d54336af598b9470ccd5300e2f58ee506f5ca13", + "sha256:21f9ddc0ff6e07f7d7b6b484eb9da2c03bc9931dd13e36796b111d631f7135a3", + "sha256:247873cda726f7956f745a3e03158b00de79c4abea8776dc2f611d5ba368d72d", + "sha256:3aa31c42f29f1da6f4fd41433ad15052d5ff045f2214002e027a321f79d64e2c", + "sha256:475f694f87dbc619010b26de7d0fc575a4accf503f2200885cc21f526bffe2ad", + "sha256:4b5e332a24bf6e2fda1f51ca2a57ae1083352293a08eeea1fa1112dc7dd542d1", + "sha256:570d521660574aca40be7b4d532dfb6f156aad7b16b5ed62d1534f64f1ef72d8", + "sha256:59072de7def0690dd13112d2bdb453e20570a97297070f876fbbb7cbc1c26b05", + "sha256:5f0b658989e918ef187f8a08db0420528126f2c7da182a7b9f8bf7f85144d4e4", + "sha256:649199c84a966917d86cdc2046e03d536763576c0b2a756059ae0b3a9656bc20", + "sha256:6645fc9b4705ae8fbf1ef7674f416f89ae1559deec810f6dd15197dfa52893da", + "sha256:6872dd54d4e398d781efe8fe2e2d7eafe4450d61b5c4898aced7610109a6df75", + "sha256:6ce34fbc251fc0d691c8d131250ba6f42fd2b28ef28558d528ba8c558cb28804", + "sha256:73920d167a0a4d1006f5f3b9a3efce6f0e5e883a99599d38206d43f27697df00", + "sha256:8a671732b87ae423e34b51139628123bc0306c2cb85c226e71b28d3d57d7e42a", + "sha256:8d517e8fda2efebca27c2018e14c90ed7dc3f04d7098b3da2912e62a1a5585fe", + "sha256:9475a008eb7279e20d400c76471843c321b46acacc7ee3de0b47233a1e3fa2cf", + "sha256:96947b8cd7b3148fb0e6549fcb31258a736595d6f2a599f8cd450e9a80a14781", + "sha256:abf229f24daa93f67ac53e2e17c8798a71a01711eb9fcdd029abba8637164338", + "sha256:b1ab012f276df584beb74f81acb63905762c25803ece647016613c3d6ad4e432", + "sha256:b22b33f6f0071fe57cb4e9158f353c88d41e739a3ec0d76f7b704539e7076427", + "sha256:b3b2d53274858e50ad2ffdd6d97ce1d014e1e530f82ec8b307edd5d4c921badf", + "sha256:bab26a729befc7b9fab9ded1bba9c51b785188b79f8a2796ba03e7e734269e2e", + "sha256:daa1a593629aa49f506eddc9d23dc7f89b35693b90e1fbcd4480182d1203ea90", + "sha256:dd111280ce40e89fd17b19c1269fd1b74a30fce9d44a550840e86edb33924eb8", + "sha256:e0b86084f1e2e78c451994410de756deba206884d6bed68d5a3d7f39ff5fea1d", + "sha256:eb86520753560a7e89639500e2a254bb6f683342af598088cb72c73edcad21e6", + "sha256:ff18c5c40a38d41811c23e2480615425c97ea81fd7e9118b8b899c512d97c737" ], "index": "pypi", - "version": "==2.7.4" + "version": "==2.7.6.1" }, "py": { "hashes": [ - "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", - "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", + "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" ], - "version": "==1.5.3" + "version": "==1.7.0" }, "pycodestyle": { "hashes": [ - "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", - "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" + "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", + "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], - "version": "==2.3.1" + "version": "==2.4.0" }, "pyflakes": { "hashes": [ - "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", - "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" + "sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49", + "sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae" ], - "version": "==1.6.0" + "version": "==2.0.0" }, "pytest": { "hashes": [ - "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", - "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1" + "sha256:f689bf2fc18c4585403348dd56f47d87780bf217c53ed9ae7a3e2d7faa45f8e9", + "sha256:f812ea39a0153566be53d88f8de94839db1e8a05352ed8a49525d7d7f37861e9" ], "index": "pypi", - "version": "==3.5.0" + "version": "==4.0.2" }, "pytest-django": { "hashes": [ - "sha256:00995c2999b884a38ae9cd30a8c00ed32b3d38c1041250ea84caf18085589662", - "sha256:038ccc5a9daa1b1b0eb739ab7dce54e495811eca5ea3af4815a2a3ac45152309" + "sha256:deffd9d65827c582bd0a85638a0fe52f0eb65a764872ddcee9ce51cdf6ae9f55", + "sha256:fe1f71a0171f6b7edac37654da0904c9bd5ffba5221ab5a76779ab870611f41f" ], "index": "pypi", - "version": "==3.1.2" + "version": "==3.4.4" }, "python-dateutil": { "hashes": [ - "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", - "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", + "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" ], - "version": "==2.7.2" + "version": "==2.7.5" }, "pytz": { "hashes": [ - "sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd", - "sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5", - "sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0", - "sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d", - "sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9", - "sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef", - "sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f", - "sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe", - "sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda" + "sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca", + "sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6" ], - "version": "==2018.3" + "version": "==2018.7" }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "version": "==1.11.0" + "version": "==1.12.0" }, "text-unidecode": { "hashes": [ @@ -195,7 +207,134 @@ ], "index": "pypi", "version": "==0.12.0" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" } }, - "develop": {} + "develop": { + "astroid": { + "hashes": [ + "sha256:35b032003d6a863f5dcd7ec11abd5cd5893428beaa31ab164982403bcb311f22", + "sha256:6a5d668d7dc69110de01cdf7aeec69a679ef486862a0850cc0fd5571505b6b7e" + ], + "version": "==2.1.0" + }, + "isort": { + "hashes": [ + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" + ], + "version": "==4.3.4" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", + "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", + "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", + "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", + "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", + "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", + "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", + "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", + "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", + "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", + "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", + "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", + "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", + "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", + "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", + "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", + "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", + "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", + "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", + "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", + "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", + "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", + "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", + "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", + "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", + "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", + "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", + "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", + "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" + ], + "version": "==1.3.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "mypy": { + "hashes": [ + "sha256:12d965c9c4e8a625673aec493162cf390e66de12ef176b1f4821ac00d55f3ab3", + "sha256:38d5b5f835a81817dcc0af8d155bce4e9aefa03794fe32ed154d6612e83feafa" + ], + "index": "pypi", + "version": "==0.650" + }, + "mypy-extensions": { + "hashes": [ + "sha256:37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", + "sha256:b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e" + ], + "version": "==0.4.1" + }, + "pylint": { + "hashes": [ + "sha256:689de29ae747642ab230c6d37be2b969bf75663176658851f456619aacf27492", + "sha256:771467c434d0d9f081741fec1d64dfb011ed26e65e12a28fe06ca2f61c4d556c" + ], + "index": "pypi", + "version": "==2.2.2" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "typed-ast": { + "hashes": [ + "sha256:0555eca1671ebe09eb5f2176723826f6f44cca5060502fea259de9b0e893ab53", + "sha256:0ca96128ea66163aea13911c9b4b661cb345eb729a20be15c034271360fc7474", + "sha256:16ccd06d614cf81b96de42a37679af12526ea25a208bce3da2d9226f44563868", + "sha256:1e21ae7b49a3f744958ffad1737dfbdb43e1137503ccc59f4e32c4ac33b0bd1c", + "sha256:37670c6fd857b5eb68aa5d193e14098354783b5138de482afa401cc2644f5a7f", + "sha256:46d84c8e3806619ece595aaf4f37743083f9454c9ea68a517f1daa05126daf1d", + "sha256:5b972bbb3819ece283a67358103cc6671da3646397b06e7acea558444daf54b2", + "sha256:6306ffa64922a7b58ee2e8d6f207813460ca5a90213b4a400c2e730375049246", + "sha256:6cb25dc95078931ecbd6cbcc4178d1b8ae8f2b513ae9c3bd0b7f81c2191db4c6", + "sha256:7e19d439fee23620dea6468d85bfe529b873dace39b7e5b0c82c7099681f8a22", + "sha256:7f5cd83af6b3ca9757e1127d852f497d11c7b09b4716c355acfbebf783d028da", + "sha256:81e885a713e06faeef37223a5b1167615db87f947ecc73f815b9d1bbd6b585be", + "sha256:94af325c9fe354019a29f9016277c547ad5d8a2d98a02806f27a7436b2da6735", + "sha256:b1e5445c6075f509d5764b84ce641a1535748801253b97f3b7ea9d948a22853a", + "sha256:cb061a959fec9a514d243831c514b51ccb940b58a5ce572a4e209810f2507dcf", + "sha256:cc8d0b703d573cbabe0d51c9d68ab68df42a81409e4ed6af45a04a95484b96a5", + "sha256:da0afa955865920edb146926455ec49da20965389982f91e926389666f5cf86a", + "sha256:dc76738331d61818ce0b90647aedde17bbba3d3f9e969d83c1d9087b4f978862", + "sha256:e7ec9a1445d27dbd0446568035f7106fa899a36f55e52ade28020f7b3845180d", + "sha256:f741ba03feb480061ab91a465d1a3ed2d40b52822ada5b4017770dfcb88f839f", + "sha256:fe800a58547dd424cd286b7270b967b5b3316b993d86453ede184a17b5a6b17d" + ], + "markers": "python_version < '3.7' and implementation_name == 'cpython'", + "version": "==1.1.1" + }, + "wrapt": { + "hashes": [ + "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" + ], + "version": "==1.10.11" + } + } } diff --git a/README.md b/README.md index c088364..5e63916 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ assignment application for Django, designed to be dropped into an existing site * Python 3.3+ * jQuery (full version, not "slim", for drag/drop prioritization) * Bootstrap (to work with provided templates, though you can override them) +* bleach (`pip install bleach`) ## Overview @@ -166,6 +167,8 @@ The previous `tox` system was removed with the v2 release, since we no longer ai # Version History +**2.1.0** December 2018: No longer allowing Javascript in task or comment bodies. Misc bug fixes. + **2.0.3** April 2018: Bump production status in setup.py **2.0.2** April 2018: Improve notification email subjects and bodies diff --git a/todo/__init__.py b/todo/__init__.py index cf78c2a..62af3e3 100644 --- a/todo/__init__.py +++ b/todo/__init__.py @@ -1,7 +1,7 @@ """ A multi-user, multi-group task management and assignment system for Django. """ -__version__ = '2.0.3' +__version__ = '2.1.0' __author__ = 'Scot Hacker' __email__ = 'shacker@birdhouse.org' diff --git a/todo/models.py b/todo/models.py index 3a8d558..ee5955a 100644 --- a/todo/models.py +++ b/todo/models.py @@ -75,4 +75,4 @@ class Comment(models.Model): return "{author} - {snippet}...".format(author=self.author, snippet=self.body[:35]) def __str__(self): - return self.snippet + return self.snippet() diff --git a/todo/tests/test_views.py b/todo/tests/test_views.py index 74724d1..4f44e8a 100644 --- a/todo/tests/test_views.py +++ b/todo/tests/test_views.py @@ -1,5 +1,8 @@ +import bleach +import json import pytest +from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.urls import reverse @@ -85,6 +88,60 @@ def test_view_search(todo_setup, admin_client): assert response.status_code == 200 +@pytest.mark.django_db +def test_no_javascript_in_task_note(todo_setup, client): + task_list = TaskList.objects.first() + user = get_user_model().objects.get(username="u2") + title = "Some Unique String" + note = "foo bar" + data = { + "task_list": task_list.id, + "created_by": user.id, + "priority": 10, + "title": title, + "note": note, + 'add_edit_task': 'Submit' + } + + client.login(username='u2', password="password") + url = reverse('todo:list_detail', kwargs={"list_id": task_list.id, "list_slug": task_list.slug}) + + response = client.post(url, data) + assert response.status_code == 302 + + # Retrieve new task and compare notes field + task = Task.objects.get(title=title) + assert task.note != note # Should have been modified by bleach since note included javascript! + assert task.note == bleach.clean(note, strip=True) + + +@pytest.mark.django_db +def test_no_javascript_in_comments(todo_setup, client): + user = get_user_model().objects.get(username="u2") + client.login(username='u2', password="password") + + task = Task.objects.first() + task.created_by = user + task.save() + + user.groups.add(task.task_list.group) + + comment = "foo bar" + data = { + "comment-body": comment, + "add_comment": 'Submit' + } + url = reverse('todo:task_detail', kwargs={"task_id": task.id}) + + response = client.post(url, data) + assert response.status_code == 200 + + task.refresh_from_db() + newcomment = task.comment_set.last() + assert newcomment != comment # Should have been modified by bleach + assert newcomment.body == bleach.clean(comment, strip=True) + + # ### PERMISSIONS ### """ @@ -139,9 +196,9 @@ def test_view_task_mine(todo_setup, client): def test_view_task_my_group(todo_setup, client, django_user_model): - # User can always view tasks that are NOT theirs IF the task is in a shared group. - # u1 and u2 are in different groups in the fixture - - # Put them in the same group. + """User can always view tasks that are NOT theirs IF the task is in a shared group. + u1 and u2 are in different groups in the fixture - + Put them in the same group.""" g1 = Group.objects.get(name="Workgroup One") u2 = django_user_model.objects.get(username="u2") u2.groups.add(g1) diff --git a/todo/views.py b/todo/views.py index d1c20d9..ba01504 100644 --- a/todo/views.py +++ b/todo/views.py @@ -1,4 +1,5 @@ import datetime +import bleach from django.conf import settings from django.contrib import messages @@ -150,6 +151,7 @@ def list_detail(request, list_id=None, list_slug=None, view_completed=False): if form.is_valid(): new_task = form.save(commit=False) new_task.created_date = timezone.now() + new_task.note = bleach.clean(form.cleaned_data['note'], strip=True) form.save() # Send email alert only if Notify checkbox is checked AND assignee is not same as the submitter @@ -197,7 +199,7 @@ def task_detail(request, task_id: int) -> HttpResponse: Comment.objects.create( author=request.user, task=task, - body=request.POST['comment-body'], + body=bleach.clean(request.POST['comment-body'], strip=True), ) send_email_to_thread_participants( @@ -210,7 +212,9 @@ def task_detail(request, task_id: int) -> HttpResponse: form = AddEditTaskForm(request.user, request.POST, instance=task, initial={'task_list': task.task_list}) if form.is_valid(): - form.save() + item = form.save(commit=False) + item.note = bleach.clean(form.cleaned_data['note'], strip=True) + item.save() messages.success(request, "The task has been edited.") return redirect('todo:list_detail', list_id=task.task_list.id, list_slug=task.task_list.slug) else: