From 1c563690446ab3a8bacda0bd7ba8320476b7c1ac Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Thu, 9 Nov 2023 19:48:13 +0800 Subject: [PATCH 1/3] Added user model --- Pipfile | 4 + Pipfile.lock | 565 ++++++++++++++---- equipment_tracker/accounts/__init__.py | 0 equipment_tracker/accounts/admin.py | 11 + equipment_tracker/accounts/apps.py | 6 + .../accounts/migrations/0001_initial.py | 46 ++ .../accounts/migrations/__init__.py | 0 equipment_tracker/accounts/models.py | 82 +++ equipment_tracker/accounts/serializers.py | 45 ++ equipment_tracker/accounts/tests.py | 3 + equipment_tracker/accounts/urls.py | 7 + equipment_tracker/accounts/views.py | 3 + equipment_tracker/api/urls.py | 2 +- equipment_tracker/config/settings.py | 13 +- equipment_tracker/db.sqlite3 | Bin 131072 -> 131072 bytes 15 files changed, 659 insertions(+), 128 deletions(-) create mode 100644 equipment_tracker/accounts/__init__.py create mode 100644 equipment_tracker/accounts/admin.py create mode 100644 equipment_tracker/accounts/apps.py create mode 100644 equipment_tracker/accounts/migrations/0001_initial.py create mode 100644 equipment_tracker/accounts/migrations/__init__.py create mode 100644 equipment_tracker/accounts/models.py create mode 100644 equipment_tracker/accounts/serializers.py create mode 100644 equipment_tracker/accounts/tests.py create mode 100644 equipment_tracker/accounts/urls.py create mode 100644 equipment_tracker/accounts/views.py diff --git a/Pipfile b/Pipfile index 1ca75d8..627e336 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,10 @@ python-dotenv = "*" whitenoise = "*" djoser = "*" django-cors-headers = "*" +drf-spectacular = {version = "*", extras = ["sidecar"]} +django-extra-fields = "*" +pillow = "*" +psycopg2 = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 4857364..f1f704a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "78c49b7899d981508de476af5e9aa819ee18a8c6ecaa040961788004559f5cac" + "sha256": "7ca25164f3d5c5501004130b514ab73101cc9d6937aa0af8356bf65a3cb354fe" }, "pipfile-spec": 6, "requires": { @@ -24,6 +24,14 @@ "markers": "python_version >= '3.7'", "version": "==3.7.2" }, + "attrs": { + "hashes": [ + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, "certifi": { "hashes": [ "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", @@ -92,128 +100,128 @@ }, "charset-normalizer": { "hashes": [ - "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5", - "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93", - "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a", - "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d", - "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c", - "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1", - "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58", - "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2", - "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557", - "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147", - "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041", - "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2", - "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2", - "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7", - "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296", - "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690", - "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67", - "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57", - "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597", - "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846", - "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b", - "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97", - "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c", - "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62", - "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa", - "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f", - "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e", - "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821", - "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3", - "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4", - "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb", - "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727", - "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514", - "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d", - "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761", - "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55", - "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f", - "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c", - "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034", - "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6", - "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae", - "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1", - "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14", - "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1", - "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228", - "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708", - "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48", - "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f", - "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5", - "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f", - "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4", - "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8", - "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff", - "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61", - "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b", - "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97", - "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b", - "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605", - "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728", - "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d", - "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c", - "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf", - "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673", - "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1", - "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b", - "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41", - "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8", - "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f", - "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4", - "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008", - "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9", - "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5", - "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f", - "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e", - "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273", - "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45", - "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e", - "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656", - "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e", - "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c", - "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2", - "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72", - "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056", - "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397", - "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42", - "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd", - "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3", - "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213", - "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf", - "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67" + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.1" + "version": "==3.3.2" }, "cryptography": { "hashes": [ - "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67", - "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311", - "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8", - "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13", - "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143", - "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f", - "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829", - "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd", - "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397", - "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac", - "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d", - "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a", - "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839", - "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e", - "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6", - "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9", - "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860", - "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca", - "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91", - "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d", - "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714", - "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb", - "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f" + "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf", + "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84", + "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e", + "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8", + "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7", + "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1", + "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88", + "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86", + "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179", + "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81", + "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20", + "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548", + "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d", + "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d", + "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5", + "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1", + "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147", + "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936", + "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797", + "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696", + "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72", + "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da", + "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723" ], "markers": "python_version >= '3.7'", - "version": "==41.0.4" + "version": "==41.0.5" }, "defusedxml": { "hashes": [ @@ -225,11 +233,11 @@ }, "django": { "hashes": [ - "sha256:08f41f468b63335aea0d904c5729e0250300f6a1907bf293a65499496cdbc68f", - "sha256:a64d2487cdb00ad7461434320ccc38e60af9c404773a2f95ab0093b4453a3215" + "sha256:8e0f1c2c2786b5c0e39fe1afce24c926040fad47c8ea8ad30aaf1188df29fc41", + "sha256:e1d37c51ad26186de355cbcec16613ebdabfa9689bbade9c538835205a8abbe9" ], "index": "pypi", - "version": "==4.2.6" + "version": "==4.2.7" }, "django-cors-headers": { "hashes": [ @@ -239,6 +247,13 @@ "index": "pypi", "version": "==4.3.0" }, + "django-extra-fields": { + "hashes": [ + "sha256:2334e914b346c0a19a7765bf0ff7895c46cf35d5f40315a68418f44b7ddbb33b" + ], + "index": "pypi", + "version": "==3.0.2" + }, "django-templated-mail": { "hashes": [ "sha256:8db807effebb42a532622e2d142dfd453dafcd0d7794c4c3332acb90656315f9", @@ -264,11 +279,29 @@ }, "djoser": { "hashes": [ - "sha256:4aa48502df870c8b5f07109ad4a749cc881c37bb5efa85cf5462ea695a0dca8c", - "sha256:7b24718cdc51b4294b0abcf6bf0ead11aa3ca83652e351dfb04b7b8b15afa3b0" + "sha256:9deb831a1c8781ceff325699e1407b4e1be8b4588e87071621d88ba31c09349f", + "sha256:efb91ad61e4d5b8d664db029b5947df9d34078289ef2680a1ab665e047144b74" ], "index": "pypi", - "version": "==2.2.0" + "version": "==2.2.2" + }, + "drf-spectacular": { + "extras": [ + "sidecar" + ], + "hashes": [ + "sha256:aee55330a774ba8a9cbdb125714d1c9ee05a8aafd3ce3be8bfd26527649aeb44", + "sha256:c0002a820b11771fdbf37853deb371947caf0159d1afeeffe7598e964bc1db94" + ], + "index": "pypi", + "version": "==0.26.5" + }, + "drf-spectacular-sidecar": { + "hashes": [ + "sha256:3d042a6772512f4d238f0385d3430acf5f669f595fd0be2641fe6bbfb4c7b376", + "sha256:546a83c173589715e530fad211af60cbcda2db54eb9e0935d44251639332af6d" + ], + "version": "==2023.10.1" }, "idna": { "hashes": [ @@ -278,6 +311,30 @@ "markers": "python_version >= '3.5'", "version": "==3.4" }, + "inflection": { + "hashes": [ + "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", + "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2" + ], + "markers": "python_version >= '3.5'", + "version": "==0.5.1" + }, + "jsonschema": { + "hashes": [ + "sha256:c9ff4d7447eed9592c23a12ccee508baf0dd0d59650615e847feb6cdca74f392", + "sha256:eee9e502c788e89cb166d4d37f43084e3b64ab405c795c03d343a4dbc2c810fc" + ], + "markers": "python_version >= '3.8'", + "version": "==4.19.2" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1", + "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.7.1" + }, "oauthlib": { "hashes": [ "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", @@ -286,6 +343,85 @@ "markers": "python_version >= '3.6'", "version": "==3.2.2" }, + "pillow": { + "hashes": [ + "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", + "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de", + "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616", + "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839", + "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099", + "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a", + "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219", + "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106", + "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b", + "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412", + "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b", + "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7", + "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2", + "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7", + "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14", + "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f", + "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27", + "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57", + "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262", + "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28", + "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610", + "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172", + "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273", + "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e", + "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d", + "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818", + "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f", + "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9", + "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01", + "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7", + "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651", + "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312", + "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80", + "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666", + "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061", + "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b", + "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992", + "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593", + "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4", + "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db", + "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba", + "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd", + "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e", + "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212", + "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb", + "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2", + "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34", + "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256", + "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f", + "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2", + "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38", + "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996", + "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", + "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" + ], + "index": "pypi", + "version": "==10.1.0" + }, + "psycopg2": { + "hashes": [ + "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981", + "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516", + "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3", + "sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa", + "sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a", + "sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693", + "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372", + "sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e", + "sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59", + "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156", + "sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024", + "sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913", + "sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c" + ], + "index": "pypi", + "version": "==2.9.9" + }, "pycparser": { "hashes": [ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", @@ -323,6 +459,70 @@ ], "version": "==2023.3.post1" }, + "pyyaml": { + "hashes": [ + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0.1" + }, + "referencing": { + "hashes": [ + "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf", + "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0" + ], + "markers": "python_version >= '3.8'", + "version": "==0.30.2" + }, "requests": { "hashes": [ "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", @@ -339,6 +539,111 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.1" }, + "rpds-py": { + "hashes": [ + "sha256:0525847f83f506aa1e28eb2057b696fe38217e12931c8b1b02198cfe6975e142", + "sha256:05942656cb2cb4989cd50ced52df16be94d344eae5097e8583966a1d27da73a5", + "sha256:0831d3ecdea22e4559cc1793f22e77067c9d8c451d55ae6a75bf1d116a8e7f42", + "sha256:0853da3d5e9bc6a07b2486054a410b7b03f34046c123c6561b535bb48cc509e1", + "sha256:08e6e7ff286254016b945e1ab632ee843e43d45e40683b66dd12b73791366dd1", + "sha256:0a38612d07a36138507d69646c470aedbfe2b75b43a4643f7bd8e51e52779624", + "sha256:0bedd91ae1dd142a4dc15970ed2c729ff6c73f33a40fa84ed0cdbf55de87c777", + "sha256:0c5441b7626c29dbd54a3f6f3713ec8e956b009f419ffdaaa3c80eaf98ddb523", + "sha256:0e9e976e0dbed4f51c56db10831c9623d0fd67aac02853fe5476262e5a22acb7", + "sha256:0fadfdda275c838cba5102c7f90a20f2abd7727bf8f4a2b654a5b617529c5c18", + "sha256:1096ca0bf2d3426cbe79d4ccc91dc5aaa73629b08ea2d8467375fad8447ce11a", + "sha256:171d9a159f1b2f42a42a64a985e4ba46fc7268c78299272ceba970743a67ee50", + "sha256:188912b22b6c8225f4c4ffa020a2baa6ad8fabb3c141a12dbe6edbb34e7f1425", + "sha256:1b4cf9ab9a0ae0cb122685209806d3f1dcb63b9fccdf1424fb42a129dc8c2faa", + "sha256:1e04581c6117ad9479b6cfae313e212fe0dfa226ac727755f0d539cd54792963", + "sha256:1fa73ed22c40a1bec98d7c93b5659cd35abcfa5a0a95ce876b91adbda170537c", + "sha256:2124f9e645a94ab7c853bc0a3644e0ca8ffbe5bb2d72db49aef8f9ec1c285733", + "sha256:240687b5be0f91fbde4936a329c9b7589d9259742766f74de575e1b2046575e4", + "sha256:25740fb56e8bd37692ed380e15ec734be44d7c71974d8993f452b4527814601e", + "sha256:27ccc93c7457ef890b0dd31564d2a05e1aca330623c942b7e818e9e7c2669ee4", + "sha256:281c8b219d4f4b3581b918b816764098d04964915b2f272d1476654143801aa2", + "sha256:2d34a5450a402b00d20aeb7632489ffa2556ca7b26f4a63c35f6fccae1977427", + "sha256:301bd744a1adaa2f6a5e06c98f1ac2b6f8dc31a5c23b838f862d65e32fca0d4b", + "sha256:30e5ce9f501fb1f970e4a59098028cf20676dee64fc496d55c33e04bbbee097d", + "sha256:33ab498f9ac30598b6406e2be1b45fd231195b83d948ebd4bd77f337cb6a2bff", + "sha256:35585a8cb5917161f42c2104567bb83a1d96194095fc54a543113ed5df9fa436", + "sha256:389c0e38358fdc4e38e9995e7291269a3aead7acfcf8942010ee7bc5baee091c", + "sha256:3acadbab8b59f63b87b518e09c4c64b142e7286b9ca7a208107d6f9f4c393c5c", + "sha256:3b7a64d43e2a1fa2dd46b678e00cabd9a49ebb123b339ce799204c44a593ae1c", + "sha256:3c8c0226c71bd0ce9892eaf6afa77ae8f43a3d9313124a03df0b389c01f832de", + "sha256:429349a510da82c85431f0f3e66212d83efe9fd2850f50f339341b6532c62fe4", + "sha256:466030a42724780794dea71eb32db83cc51214d66ab3fb3156edd88b9c8f0d78", + "sha256:47aeceb4363851d17f63069318ba5721ae695d9da55d599b4d6fb31508595278", + "sha256:48aa98987d54a46e13e6954880056c204700c65616af4395d1f0639eba11764b", + "sha256:4b2416ed743ec5debcf61e1242e012652a4348de14ecc7df3512da072b074440", + "sha256:4d0a675a7acbbc16179188d8c6d0afb8628604fc1241faf41007255957335a0b", + "sha256:4eb74d44776b0fb0782560ea84d986dffec8ddd94947f383eba2284b0f32e35e", + "sha256:4f8a1d990dc198a6c68ec3d9a637ba1ce489b38cbfb65440a27901afbc5df575", + "sha256:513ccbf7420c30e283c25c82d5a8f439d625a838d3ba69e79a110c260c46813f", + "sha256:5210a0018c7e09c75fa788648617ebba861ae242944111d3079034e14498223f", + "sha256:54cdfcda59251b9c2f87a05d038c2ae02121219a04d4a1e6fc345794295bdc07", + "sha256:56dd500411d03c5e9927a1eb55621e906837a83b02350a9dc401247d0353717c", + "sha256:57ec6baec231bb19bb5fd5fc7bae21231860a1605174b11585660236627e390e", + "sha256:5f1519b080d8ce0a814f17ad9fb49fb3a1d4d7ce5891f5c85fc38631ca3a8dc4", + "sha256:6174d6ad6b58a6bcf67afbbf1723420a53d06c4b89f4c50763d6fa0a6ac9afd2", + "sha256:68172622a5a57deb079a2c78511c40f91193548e8ab342c31e8cb0764d362459", + "sha256:6915fc9fa6b3ec3569566832e1bb03bd801c12cea030200e68663b9a87974e76", + "sha256:6b75b912a0baa033350367a8a07a8b2d44fd5b90c890bfbd063a8a5f945f644b", + "sha256:6f5dcb658d597410bb7c967c1d24eaf9377b0d621358cbe9d2ff804e5dd12e81", + "sha256:6f8d7fe73d1816eeb5378409adc658f9525ecbfaf9e1ede1e2d67a338b0c7348", + "sha256:7036316cc26b93e401cedd781a579be606dad174829e6ad9e9c5a0da6e036f80", + "sha256:7188ddc1a8887194f984fa4110d5a3d5b9b5cd35f6bafdff1b649049cbc0ce29", + "sha256:761531076df51309075133a6bc1db02d98ec7f66e22b064b1d513bc909f29743", + "sha256:7979d90ee2190d000129598c2b0c82f13053dba432b94e45e68253b09bb1f0f6", + "sha256:8015835494b21aa7abd3b43fdea0614ee35ef6b03db7ecba9beb58eadf01c24f", + "sha256:81c4d1a3a564775c44732b94135d06e33417e829ff25226c164664f4a1046213", + "sha256:81cf9d306c04df1b45971c13167dc3bad625808aa01281d55f3cf852dde0e206", + "sha256:88857060b690a57d2ea8569bca58758143c8faa4639fb17d745ce60ff84c867e", + "sha256:8c567c664fc2f44130a20edac73e0a867f8e012bf7370276f15c6adc3586c37c", + "sha256:91bd2b7cf0f4d252eec8b7046fa6a43cee17e8acdfc00eaa8b3dbf2f9a59d061", + "sha256:9620650c364c01ed5b497dcae7c3d4b948daeae6e1883ae185fef1c927b6b534", + "sha256:9b007c2444705a2dc4a525964fd4dd28c3320b19b3410da6517cab28716f27d3", + "sha256:9bf9acce44e967a5103fcd820fc7580c7b0ab8583eec4e2051aec560f7b31a63", + "sha256:a239303acb0315091d54c7ff36712dba24554993b9a93941cf301391d8a997ee", + "sha256:a2baa6be130e8a00b6cbb9f18a33611ec150b4537f8563bddadb54c1b74b8193", + "sha256:a54917b7e9cd3a67e429a630e237a90b096e0ba18897bfb99ee8bd1068a5fea0", + "sha256:a689e1ded7137552bea36305a7a16ad2b40be511740b80748d3140614993db98", + "sha256:a952ae3eb460c6712388ac2ec706d24b0e651b9396d90c9a9e0a69eb27737fdc", + "sha256:aa32205358a76bf578854bf31698a86dc8b2cb591fd1d79a833283f4a403f04b", + "sha256:b2287c09482949e0ca0c0eb68b2aca6cf57f8af8c6dfd29dcd3bc45f17b57978", + "sha256:b6b0e17d39d21698185097652c611f9cf30f7c56ccec189789920e3e7f1cee56", + "sha256:b710bf7e7ae61957d5c4026b486be593ed3ec3dca3e5be15e0f6d8cf5d0a4990", + "sha256:b8e11715178f3608874508f08e990d3771e0b8c66c73eb4e183038d600a9b274", + "sha256:b92aafcfab3d41580d54aca35a8057341f1cfc7c9af9e8bdfc652f83a20ced31", + "sha256:bec29b801b4adbf388314c0d050e851d53762ab424af22657021ce4b6eb41543", + "sha256:c694bee70ece3b232df4678448fdda245fd3b1bb4ba481fb6cd20e13bb784c46", + "sha256:c6b52b7028b547866c2413f614ee306c2d4eafdd444b1ff656bf3295bf1484aa", + "sha256:cb41ad20064e18a900dd427d7cf41cfaec83bcd1184001f3d91a1f76b3fcea4e", + "sha256:cd316dbcc74c76266ba94eb021b0cc090b97cca122f50bd7a845f587ff4bf03f", + "sha256:ced40cdbb6dd47a032725a038896cceae9ce267d340f59508b23537f05455431", + "sha256:d1c562a9bb72244fa767d1c1ab55ca1d92dd5f7c4d77878fee5483a22ffac808", + "sha256:d389ff1e95b6e46ebedccf7fd1fadd10559add595ac6a7c2ea730268325f832c", + "sha256:d56b1cd606ba4cedd64bb43479d56580e147c6ef3f5d1c5e64203a1adab784a2", + "sha256:d72a4315514e5a0b9837a086cb433b004eea630afb0cc129de76d77654a9606f", + "sha256:d9e7f29c00577aff6b318681e730a519b235af292732a149337f6aaa4d1c5e31", + "sha256:dbc25baa6abb205766fb8606f8263b02c3503a55957fcb4576a6bb0a59d37d10", + "sha256:e57919c32ee295a2fca458bb73e4b20b05c115627f96f95a10f9f5acbd61172d", + "sha256:e5bbe011a2cea9060fef1bb3d668a2fd8432b8888e6d92e74c9c794d3c101595", + "sha256:e6aea5c0eb5b0faf52c7b5c4a47c8bb64437173be97227c819ffa31801fa4e34", + "sha256:e888be685fa42d8b8a3d3911d5604d14db87538aa7d0b29b1a7ea80d354c732d", + "sha256:eebaf8c76c39604d52852366249ab807fe6f7a3ffb0dd5484b9944917244cdbe", + "sha256:efbe0b5e0fd078ed7b005faa0170da4f72666360f66f0bb2d7f73526ecfd99f9", + "sha256:efddca2d02254a52078c35cadad34762adbae3ff01c6b0c7787b59d038b63e0d", + "sha256:f05450fa1cd7c525c0b9d1a7916e595d3041ac0afbed2ff6926e5afb6a781b7f", + "sha256:f12d69d568f5647ec503b64932874dade5a20255736c89936bf690951a5e79f5", + "sha256:f45321224144c25a62052035ce96cbcf264667bcb0d81823b1bbc22c4addd194", + "sha256:f62581d7e884dd01ee1707b7c21148f61f2febb7de092ae2f108743fcbef5985", + "sha256:f8832a4f83d4782a8f5a7b831c47e8ffe164e43c2c148c8160ed9a6d630bc02a", + "sha256:fa35ad36440aaf1ac8332b4a4a433d4acd28f1613f0d480995f5cfd3580e90b7" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.0" + }, "social-auth-app-django": { "hashes": [ "sha256:09ac02a063cb313eed5e9ef2f9ac4477c8bf5bbd685925ff3aba43f9072f1bbb", @@ -349,11 +654,11 @@ }, "social-auth-core": { "hashes": [ - "sha256:9791d7c7aee2ac8517fe7a2ea2f942a8a5492b3a4ccb44a9b0dacc87d182f2aa", - "sha256:ea7a19c46b791b767e95f467881b53c5fd0d1efb40048d9ed3dbc46daa05c954" + "sha256:3d4154f45c0bacffe54ccf4361bce7e66cf5f5cd1bb0ebb7507ad09a1b07d9d9", + "sha256:f4ae5d8e503a401f319498bcad59fd1f6c473517eeae89c22299250f63c33365" ], - "markers": "python_version >= '3.6'", - "version": "==4.4.2" + "markers": "python_version >= '3.8'", + "version": "==4.5.0" }, "sqlparse": { "hashes": [ @@ -371,6 +676,14 @@ "markers": "sys_platform == 'win32'", "version": "==2023.3" }, + "uritemplate": { + "hashes": [ + "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", + "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + ], + "markers": "python_version >= '3.6'", + "version": "==4.1.1" + }, "urllib3": { "hashes": [ "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", diff --git a/equipment_tracker/accounts/__init__.py b/equipment_tracker/accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/equipment_tracker/accounts/admin.py b/equipment_tracker/accounts/admin.py new file mode 100644 index 0000000..81a42c3 --- /dev/null +++ b/equipment_tracker/accounts/admin.py @@ -0,0 +1,11 @@ +from django import forms +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from .models import CustomUser + + +class CustomUserAdmin(UserAdmin): + model = CustomUser + + +admin.site.register(CustomUser, CustomUserAdmin) diff --git a/equipment_tracker/accounts/apps.py b/equipment_tracker/accounts/apps.py new file mode 100644 index 0000000..3e3c765 --- /dev/null +++ b/equipment_tracker/accounts/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'accounts' diff --git a/equipment_tracker/accounts/migrations/0001_initial.py b/equipment_tracker/accounts/migrations/0001_initial.py new file mode 100644 index 0000000..4e58eae --- /dev/null +++ b/equipment_tracker/accounts/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 4.2.7 on 2023-11-09 11:42 + +import accounts.models +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('first_name', models.CharField(max_length=100)), + ('last_name', models.CharField(max_length=100)), + ('is_active', models.BooleanField(default=False)), + ('avatar', models.ImageField(null=True, upload_to=accounts.models.CustomUser._get_upload_to)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/equipment_tracker/accounts/migrations/__init__.py b/equipment_tracker/accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/equipment_tracker/accounts/models.py b/equipment_tracker/accounts/models.py new file mode 100644 index 0000000..cf14fa9 --- /dev/null +++ b/equipment_tracker/accounts/models.py @@ -0,0 +1,82 @@ +from django.db import models +from django.contrib.auth.models import AbstractUser +from django.db import models +from django.db.models.signals import post_migrate +from django.dispatch import receiver +import os +from uuid import uuid4 + + +class CustomUser(AbstractUser): + # Function for avatar uploads + def _get_upload_to(instance, filename): + base_filename, file_extension = os.path.splitext(filename) + # Get the student ID number + ext = base_filename.split('.')[-1] + filename = '{}.{}'.format(uuid4().hex, ext) + + student_id = str(instance.student_id_number) + new_filename = f"{student_id}_{filename}_{file_extension}" + return os.path.join('avatars', new_filename) + + # Delete old avatar file if new one is uploaded + def save(self, *args, **kwargs): + try: + # is the object in the database yet? + this = CustomUser.objects.get(id=self.id) + if this.avatar != self.avatar: + this.avatar.delete(save=False) + except: + pass # when new photo then we do nothing, normal case + super(CustomUser, self).save(*args, **kwargs) + + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + # Email inherited from base user class + # Username inherited from base user class + # Password inherited from base user class + # is_admin inherited from base user class + is_active = models.BooleanField(default=False) + avatar = models.ImageField(upload_to=_get_upload_to, null=True) + + @property + def full_name(self): + return f"{self.first_name} {self.last_name}" + pass + + +@receiver(post_migrate) +def create_superuser(sender, **kwargs): + if sender.name == 'accounts': + User = CustomUser + username = os.getenv('DJANGO_ADMIN_USERNAME') + email = os.getenv('DJANGO_ADMIN_EMAIL') + password = os.getenv('DJANGO_ADMIN_PASSWORD') + first_name = 'Admin' + last_name = 'Admin' + + if not User.objects.filter(username=username).exists(): + # Create the superuser with is_active set to False + superuser = User.objects.create_superuser( + username=username, email=email, password=password, first_name=first_name, last_name=last_name) + + # Activate the superuser + superuser.is_active = True + print('Created admin account') + superuser.save() + + username = 'usertest1' + email = os.getenv('DJANGO_ADMIN_EMAIL') + password = os.getenv('DJANGO_ADMIN_PASSWORD') + first_name = 'Test' + last_name = 'User' + + if not User.objects.filter(username=username).exists(): + # Create the superuser with is_active set to False + user = User.objects.create_user( + username=username, email=email, password=password, first_name=first_name, last_name=last_name) + + # Activate the user + user.is_active = True + print('Created debug user account') + user.save() diff --git a/equipment_tracker/accounts/serializers.py b/equipment_tracker/accounts/serializers.py new file mode 100644 index 0000000..f862d18 --- /dev/null +++ b/equipment_tracker/accounts/serializers.py @@ -0,0 +1,45 @@ +from djoser.serializers import UserCreateSerializer as BaseUserRegistrationSerializer +from djoser.serializers import UserSerializer as BaseUserSerializer +from django.core import exceptions as django_exceptions +from rest_framework import serializers +from accounts.models import CustomUser +from rest_framework.settings import api_settings +from django.contrib.auth.password_validation import validate_password +from django.utils.encoding import smart_str +from drf_spectacular.utils import extend_schema_field +from drf_spectacular.types import OpenApiTypes +from drf_extra_fields.fields import Base64ImageField + +# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here + + +class CustomUserSerializer(BaseUserSerializer): + avatar = Base64ImageField() + + class Meta(BaseUserSerializer.Meta): + model = CustomUser + fields = ('username', 'email', 'avatar', 'first_name', 'last_name',) + + +class UserRegistrationSerializer(serializers.ModelSerializer): + email = serializers.EmailField(required=True) + password = serializers.CharField( + write_only=True, style={'input_type': 'password', 'placeholder': 'Password'}) + + class Meta: + model = CustomUser # Use your custom user model here + fields = ('username', 'email', 'password', 'avatar', + 'first_name', 'last_name') + + def validate(self, attrs): + user = self.Meta.model(**attrs) + password = attrs.get("password") + try: + validate_password(password, user) + except django_exceptions.ValidationError as e: + serializer_error = serializers.as_serializer_error(e) + raise serializers.ValidationError( + {"password": serializer_error[api_settings.NON_FIELD_ERRORS_KEY]} + ) + + return super().validate(attrs) diff --git a/equipment_tracker/accounts/tests.py b/equipment_tracker/accounts/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/equipment_tracker/accounts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/equipment_tracker/accounts/urls.py b/equipment_tracker/accounts/urls.py new file mode 100644 index 0000000..22c121e --- /dev/null +++ b/equipment_tracker/accounts/urls.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('', include('djoser.urls')), + path('', include('djoser.urls.jwt')), +] diff --git a/equipment_tracker/accounts/views.py b/equipment_tracker/accounts/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/equipment_tracker/accounts/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/equipment_tracker/api/urls.py b/equipment_tracker/api/urls.py index 130dc54..14fb12e 100644 --- a/equipment_tracker/api/urls.py +++ b/equipment_tracker/api/urls.py @@ -1,5 +1,5 @@ from django.urls import path, include urlpatterns = [ - path('accounts/', include('djoser.urls')) + path('accounts/', include('accounts.urls')) ] diff --git a/equipment_tracker/config/settings.py b/equipment_tracker/config/settings.py index 7954525..0ba6849 100644 --- a/equipment_tracker/config/settings.py +++ b/equipment_tracker/config/settings.py @@ -65,7 +65,8 @@ INSTALLED_APPS = [ 'rest_framework', 'rest_framework_simplejwt', 'djoser', - 'corsheaders' + 'corsheaders', + 'accounts' ] MIDDLEWARE = [ @@ -139,11 +140,21 @@ DATABASES = { } } +AUTH_USER_MODEL = 'accounts.CustomUser' + DJOSER = { 'SEND_ACTIVATION_EMAIL': True, 'SEND_CONFIRMATION_EMAIL': True, + 'EMAIL': { + 'activation': 'config.email.ActivationEmail' + }, 'ACTIVATION_URL': 'activation/{uid}/{token}', 'USER_AUTHENTICATION_RULES': ['djoser.authentication.TokenAuthenticationRule'], + 'SERIALIZERS': { + 'user': 'accounts.serializers.CustomUserSerializer', + 'current_user': 'accounts.serializers.CustomUserSerializer', + 'user_create': 'accounts.serializers.UserRegistrationSerializer', + }, } # Password validation diff --git a/equipment_tracker/db.sqlite3 b/equipment_tracker/db.sqlite3 index 2cd41471cc632d87bc3a3879eb5c2c9fbcfbd7df..151391c1e3878bf8ec113c43d881832c7b9b3572 100644 GIT binary patch delta 5729 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 Date: Thu, 9 Nov 2023 19:52:03 +0800 Subject: [PATCH 2/3] Added schema documentation --- .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 198 bytes .../__pycache__/admin.cpython-311.pyc | Bin 0 -> 790 bytes .../accounts/__pycache__/apps.cpython-311.pyc | Bin 0 -> 573 bytes .../__pycache__/models.cpython-311.pyc | Bin 0 -> 4479 bytes .../__pycache__/serializers.cpython-311.pyc | Bin 0 -> 3397 bytes .../accounts/__pycache__/urls.cpython-311.pyc | Bin 0 -> 519 bytes .../api/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 193 bytes .../api/__pycache__/urls.cpython-311.pyc | Bin 0 -> 382 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 196 bytes .../__pycache__/settings.cpython-311.pyc | Bin 0 -> 5915 bytes .../config/__pycache__/urls.cpython-311.pyc | Bin 0 -> 1197 bytes equipment_tracker/config/settings.py | 15 + equipment_tracker/config/urls.py | 8 +- equipment_tracker/schema.yml | 710 ++++++++++++++++++ 14 files changed, 732 insertions(+), 1 deletion(-) create mode 100644 equipment_tracker/accounts/__pycache__/__init__.cpython-311.pyc create mode 100644 equipment_tracker/accounts/__pycache__/admin.cpython-311.pyc create mode 100644 equipment_tracker/accounts/__pycache__/apps.cpython-311.pyc create mode 100644 equipment_tracker/accounts/__pycache__/models.cpython-311.pyc create mode 100644 equipment_tracker/accounts/__pycache__/serializers.cpython-311.pyc create mode 100644 equipment_tracker/accounts/__pycache__/urls.cpython-311.pyc create mode 100644 equipment_tracker/api/__pycache__/__init__.cpython-311.pyc create mode 100644 equipment_tracker/api/__pycache__/urls.cpython-311.pyc create mode 100644 equipment_tracker/config/__pycache__/__init__.cpython-311.pyc create mode 100644 equipment_tracker/config/__pycache__/settings.cpython-311.pyc create mode 100644 equipment_tracker/config/__pycache__/urls.cpython-311.pyc create mode 100644 equipment_tracker/schema.yml diff --git a/equipment_tracker/accounts/__pycache__/__init__.cpython-311.pyc b/equipment_tracker/accounts/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d605aa040b6d84b9950525d37981c597610518a GIT binary patch literal 198 zcmZ3^%ge<81P2cKq=M+jAOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnuSi#`n1G`E ztkmR^;uy~m1=k!PE3+(B!6e4Dur#wEH#M&$q$n{tJGDsH2}I?k#H7L`;!7YhF^S2^ z`K5V46XN4D^D;}~V%&|s7^dTKY#B%`+a^+KCZ9#LCJ?NPnbafexlQf{TD3X zD=-HNl%&9kPY7ZoHMr@U8k?!bZQoYdqIT+V*LMjR@DQkT1k`2rsR{5|%~pJmnX_K! zo#-2MUbixrd8dXtrDiLty7vsmy)$&jMB1-%!3zWtSM?|H$*J#@}gFSw`wpeo9o zV?1uFv=-AS%PY#vfq_pb_y#k5ixNd*$ic-)U2$h@OD_zwh_f)1{V?P?ty08mVR%qQ zX`2zQDkyE0Wa%eZBFFiQ>2~l`t%(` zy*uqo-4&b4#fLBE$}CJmNCVgERc&BYuWAFg>Q!yvM!l*Fhmg$${BMqvUl{#;k@A2z ZNBti#{0770$0viYu=O3b>Q42={{U=T$1DH< literal 0 HcmV?d00001 diff --git a/equipment_tracker/accounts/__pycache__/apps.cpython-311.pyc b/equipment_tracker/accounts/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a01fe93c51d155a4fe85e6f779822d49d2e7ebc GIT binary patch literal 573 zcmZut%SyvQ6upzAQu`1QEOa5%Wfo@TLPUgCtB6tr>%tHiVrE)W(*V|I;H5f_v;vkC(vpr9fG z>?~46BB&A(nTHfD)eXZ5?Z8hQZr4apx4Vu)E|tDRsO2jSvs(`X=fI>EiSl|XZ^^kR zkFl-yDaKI&W2O!*j!PI1LfuN46+%0DXa!hj9=H>mNSu3y8NcBCyt%ENdQOiTfv+94 zYfXzG^P1K+wdNo+-9EL0wx=6c)Z1wAViS#K1P&5L%dVyAuInrAjmIY&Cy4>S%F^&> zO{!aCsWK_94)^);%9*w$i%~Hh05|gZ%oD2;N3n2;p?Q8M`QKe{nYDb>{xM5a5g{~z Z_3`g#x*(v+6#l0Bi%mMrq*f)}TmLUKD literal 0 HcmV?d00001 diff --git a/equipment_tracker/accounts/__pycache__/models.cpython-311.pyc b/equipment_tracker/accounts/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1db7fafbe0b334dfdb41a89ddb1a15f15415701 GIT binary patch literal 4479 zcmcH-TWk~A_0G$lG2__52{<7O&VvO9>hMS?tq^KR!me4!u1L0Yt*E1kXOcMhk)0Vs zHrQ3vMyiY0C0bE|x?9PWC{0DA_LJXARn^aNG*zsTB1NiJDt|`VkBFc4+?jZs3DDAy zy`DL9?z!jQIrrT28vnuX_aSHlf4eFV@Cf}Acj}GVLAHJa$U`I{iAbXikst_+lW8(T zB`6EuO{dayhDk6Molbi)-h|h}nKYYVVV)<=Wqb)Afk^ZolDtbuVrA+Hh0s&D?UvX_ zBH1f5PY9sGZ8wQqLQepFS|^|cFEL{%>U)kUQNr|Oa*~`@0pkZJRZS6-+Q+J_;Qm}r z)r3rHS`jrF`m7=+<!@v!OQ;F zD5$A~=7~fAE6MZ?zhKsaBmFs$Us2I_loufSl(9nE=cI%@^Xo1Ee1vJandv1w~ zOo90dNpyj*AoUgcEmQQoK?lwm)z`vLi79y8?*?sqMqd)K=l_Pbz}zXu?i5WzFumd} zQ4O4Hrc6ETF#0Y+4N6}sw_C&CX5O27CEb?a#@qYFZ4B* zH2JK2+hJGnyCZgcd1K^<6CWwLSvjex6Y=rLNE$G3ok;)0$fx<#Tn2<12Uoi(E8n|> zA6aQat`7*<31MVHOeS;rEUaL=Xl(8?vq_kiH6cHj&WVzsR$ zA71?O;_r|C?%3mFk58m`6+6Auyh|G5*Ib=+ok zkE?)FQL~PFfI&O>O>2&FX!m%z9=kz~Mw7@@%5DAx%6hvIfj&W5YM%N8-6lw+`5QBK zJ3;}u&3qPHiPZ{33Khu5#1~d(0Q0ADSS3@^Wq8o4cuS753U(gTo13%@$)w=ym2OP( z*j{0JAau)`3~rF0lNF^0#-a?&meW%vEh^Kh>A88^deYiVN;Nq_NTx+q6$BM;7F+A0 zas)7I>Ox?bHDL)3!if5F0NabGMtZpBZ$j@Fp`+`e=vpYcGQN644@E1X0V6a}8mS+GTdw0PwwqmG%&Ualq4V5Y-6iJ4Ooeje-LrAwET5S>IGj zfy8Kq3=XtuqftWXh3P7u6|r<`a#Qe9i*KQ2mu4NR#orG6i)eHIfd_p$cu1hXJp6dn z#=u>aP8f~`O;)hh5d_mG2oMhP5Sav%7lcpqVj4>#2ucK4t#efHzD#atMpQ1RMK`&WDnP!6z-0R38F5;+*^gmPc23EGO=+Jg=W*A+V>w9~wj{u2 zV?ebw`y<c1MzG6OZ_fCDUZ4tHMxEogt&@&Ti{b7f3#K3!=( zZ8V==yiyHDmOVx=vNEIxPgR1ajNqxoc+H2Jdoa0sWke62sRYj$!842Ts{e55$A*INA3-J^uMACsN*#+Mad8njuyoxf)`>R1j|LdgS?(s;Oo$X}wsmvMOFkxoF8cr=+r)6=KbOJ1lqab1U}^&26%T$ z9D^$uG(s@vtZLGDwu-GBXJWhA(eyf=gTX1d)g?$OkR!bQr8~>BYu-r38`%i7mFSI7 z>w_QY@AU8FV0I(8{{g4B$11@-BiL7B_KsIuJD_B1IaJ~{AzK&L16^x@u9f%oKvyL& zU<3x%0~gi;7b<~^M&KfZXYQTNaL3pDdU#+hJWy@xTxoq4{`;&hWoi^^JNE(+Z8_pw z3zp(F7Ihyh#SQ+*2H&jjk5>3zgYVV(-YVaEfAsEXh3_!<4xR7V3>_}Lg`kJ9pzUuf zXm~Sp@WF-k(22Fsi9Le0oCHBzEI|R5hC$H7U8UiBqn4bp3g2h&eLCL<1)uF*P-v71OGMgQFR!52sZ4zDdp~I27A$}D_UThP8M0T#ih1*N^ zf?W<=RDKFwTz#nj08pa{f~cYn-F;QjS>1iTj_0(FTvrwK=bH%dtMG@0Z!ugtSs@M@#K9WbNr0jOK!PU2E{a9Aw*4Og%L^m` literal 0 HcmV?d00001 diff --git a/equipment_tracker/accounts/__pycache__/serializers.cpython-311.pyc b/equipment_tracker/accounts/__pycache__/serializers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5a7eacf9db3f646da193391be2d90116adaa6cc GIT binary patch literal 3397 zcma)8O>7&-6`o!0QvB6Yq7*q&Wy(Lb!?t2$z-bXTNNYQEfwF+nLxI9M6on3j>cq)CKu_(VD2g6d1%VO+_|#Kx6r=)%PknEeD{5&a z=y3SD{n3-6-fZnykJY%7?6`t=w%= z9QzNdixQuB&!y}#qozl1Q)Ziv{Sjp#A4PdYlA`x2wCUN6x(oU=sQcFVn!4O_y+#cO z!CS^`+J;L#&#teacI+t7VYM6z ze8w>Dv`h!>4TAxs30FZ$!K2t#_fxWm%YD97zOZzYHLA4Yxl30U=gJOn_FX!6eyMz? zWjAZI?kzI2@*!pOm+(=ymT0Ijyg;*LRw|8F9XuQYM5(#X75pwX1{3As?;ZoPdGPDz zrrT{>gHKXx3HY!1jmafG2IL-ev~Bv~XAK=?QweiW8s5Sv94;iG_@7Lpt=t`6kT z#MxOtJG+xDbh3rbD?LS4uS-30H1)L;9qr7n(C&YQO)xFa7{Nn`sJ#cE`Q;%*AQr0% z2t~7`&*g2v&XW*7L|27HI35y?6|)pe{hj=Id|L)f_y%-7UIeL&TXF#se%bLTDuzo-LymPlQ3r6F0+fm3hjpH(Q?JK_v2Y z(=jV_wc%J0?x0#@HpF(L?yPgw_0|DL;VSVNe%#jwN8ziN7lcThje|3WXky<)f}miN zNHFRa*c7ruSeQfEcYvVWML-?G0)nt7OXKsyFsvNxG7P}8h{1nPhY$I!^axV$2C0G| zXw~rZAeY!=L;8dCYw5ncA#EM@5gNmJM$h|xEJ-|!(SF;AZOGBnlt}&EQ^ZSz7KBv8 zJV#Cw_QU&%hau8$)dOD}%Fs+|#O}a{C2go4MoQ=*8FB{|gxEu?{srXK`^wLhHEE69 zi+w=WBoEJ_-?rg7$hBMPP=5HiG2{{R<3ez(cv8ho5ZN=p^VkaY7_N$sSyi*X(l7>< zh->c$r3LU@W~{*&9v9D>F4Ui}Kp9kMa0~gw!i@#v%GL6 zDdUN-P8CPE;!PZ~xAQnPCqE*`*~Xq!x=qw^s6=+xJs zJDl_+7`k5qdA3Qq+VQscaQ)%WeeEptt;yioR=W9Pk6!=H>!0X5`BysmSK5i598Zou z&CGtX`dHb?%y%;LzUa@MYI7a!)gDojqXY7^@U2ea%`fll6fSlO7yZmPo{rCU#^<|Z zGyd%S7fz>iqceNc&%L`Flk=mH^ztxP&W=8V)>FX~JpY>^xyfIxJzV>jR`{n@*iv`2 zGmt0!#2FVs@LBE$e-Tt_vo$ltR9#{W1?H3lI_hM4+eQB2<-4}H8?Or^l&iBZRWEW-o14SyW zp6!wUj|7zi7raoM;p0}d0jMeskmWK=I{bK8^p4Kl3~LEHftKkYI7*cUqYT5FeHX=} zjKY;+nZb1cE?yr7@u7uPyCiM~Zg5SQikiY=f*TwYk#qLIf8AsDPfKRYTP=m9!svq- z!Y~Nc$-Z^VvmLiY>y?HDmqCViZ9ZwSWy5X4ZNsdz9FvuV5yM3Bq7Dm=%QC2&!f|j> zWc>@GTM8~T!5smMFxRf*P3QJO=nF&)6@}-CH-gL3o9rhr1~KHm1{987lDgzQKia$G zvLEeT@_j$ryX1@??MF#o^+}|6N!gF~F8Q_}?OpPkAMIUI@}s>=&im2cOQ{lGY>uY> f%>1rU?H@MCO-caX7s=L4=foSksMtS3D`5OT_QGN- literal 0 HcmV?d00001 diff --git a/equipment_tracker/accounts/__pycache__/urls.cpython-311.pyc b/equipment_tracker/accounts/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a1c87ab62757c1e4bd3f3718438ae96b6c68898 GIT binary patch literal 519 zcmaJ-Jxjwt7`{s`ZM8%}a4)plW-ybJh=bTc5D}~tLPTQjsEPTgm!x8+jvd|n2NiMh zKR7uxkfCICaw~M}$}fDw8Ho6A6e3~Vk-bJBlvEkToL?i?xkuWV7lsbo;s z@)RK@Z6mx%^Ok2i5oIar7OCwAjH?lMg6{fKqT2W2sgg_AsBL&HUp0L%&@~f+kQx(~J6^e#U*9nPH$GH%fH}kkw(OUA=x6S#6hjVS^jy zE#o_fS@5XN7LBWL-q8)y^dk>0WQ=P2VOrRCeHuCJfXl#=eOTaw8;cm@5h@LT>j-TP z|I%>|Nh`gh{zkvqZ$4heaygO9F{vb^G9raVW4O5;%hg1##-x^z+E^0Tgh=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE5y|*CZH%k zD>b>KIL0$X!8HfS$}CG&Fo|(3EX^#)P0cF_DN0PvPA$@P0#SJ>F{v<#_!5XrOkzQ1 xOniK1US>&ryk0@&FAkgB{FKt1RJ$Tppd}z@6!Qa#56p~=j2{?aL=iJk3;+&6F=PM$ literal 0 HcmV?d00001 diff --git a/equipment_tracker/api/__pycache__/urls.cpython-311.pyc b/equipment_tracker/api/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0544ad250c009d00b9ba63f4b1f0581b9c1d9ba0 GIT binary patch literal 382 zcmZ3^%ge<81m}r0S;CetmJg2a-HTkM&6$vLGdsa2eb z$;tVpc_qdARlG2!UTINIv7aW(E$)=8#Ju!;Fu#ZysK1B>NZjHE$^%U)NiE7NUdiwo zWbm&5SF4zSqWrAXF*!T6NY@EO<)y@= z!X)BLATlwD1(`7*%k>H>e{tC4=BJeAq}mmMLJ8!*VrL-nftit!@dktH1#IX88v`q6 ogG-0>g!BpNGx9Hr>0J@iyU3z{g+>1ZGZQ~k12+g3aRAK$07&&{-2eap literal 0 HcmV?d00001 diff --git a/equipment_tracker/config/__pycache__/__init__.cpython-311.pyc b/equipment_tracker/config/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a880ab5f36e573a1d70c25311aceb5282017a571 GIT binary patch literal 196 zcmZ3^%ge<81R~jHsUZ3>h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE8Nv8CZH%k zD>b>KIL0$X!8HfS$}CG&Fo|(3EX^#)P0cF_DN0PvPA$@P0#SJ>F{v<#_!5XrOmco+ zT4s7oe0*kJW=VX!UP0wA4x8Nkl+v73yCPPgJs_79^8<+w%#4hT9~fXn5i?K>0L0HS AqW}N^ literal 0 HcmV?d00001 diff --git a/equipment_tracker/config/__pycache__/settings.cpython-311.pyc b/equipment_tracker/config/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06dbdcb670abec13036737b7ecfddb41b5d2c021 GIT binary patch literal 5915 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 literal 0 HcmV?d00001 diff --git a/equipment_tracker/config/settings.py b/equipment_tracker/config/settings.py index 0ba6849..86a6e26 100644 --- a/equipment_tracker/config/settings.py +++ b/equipment_tracker/config/settings.py @@ -66,6 +66,8 @@ INSTALLED_APPS = [ 'rest_framework_simplejwt', 'djoser', 'corsheaders', + 'drf_spectacular', + 'drf_spectacular_sidecar', 'accounts' ] @@ -125,6 +127,19 @@ REST_FRAMEWORK = { 'user': '1440/min' }, + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', +} + +# DRF-Spectacular +SPECTACULAR_SETTINGS = { + 'TITLE': 'CITC Equipment Tracker Backend', + 'DESCRIPTION': 'An IT Elective 4 Project', + 'VERSION': '1.0.0', + 'SERVE_INCLUDE_SCHEMA': False, + 'SWAGGER_UI_DIST': 'SIDECAR', + 'SWAGGER_UI_FAVICON_HREF': 'SIDECAR', + 'REDOC_DIST': 'SIDECAR', + # OTHER SETTINGS } WSGI_APPLICATION = 'config.wsgi.application' diff --git a/equipment_tracker/config/urls.py b/equipment_tracker/config/urls.py index cad3e39..8c0ff9e 100644 --- a/equipment_tracker/config/urls.py +++ b/equipment_tracker/config/urls.py @@ -16,8 +16,14 @@ Including another URLconf """ from django.contrib import admin from django.urls import path, include +from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView urlpatterns = [ path('admin/', admin.site.urls), - path('api/v1/', include('api.urls')) + path('api/v1/', include('api.urls')), + path('schema/', SpectacularAPIView.as_view(), name='schema'), + path('swagger/', + SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), + path('redoc/', + SpectacularRedocView.as_view(url_name='schema'), name='redoc'), ] diff --git a/equipment_tracker/schema.yml b/equipment_tracker/schema.yml new file mode 100644 index 0000000..01a35d8 --- /dev/null +++ b/equipment_tracker/schema.yml @@ -0,0 +1,710 @@ +openapi: 3.0.3 +info: + title: CITC Equipment Tracker Backend + version: 1.0.0 + description: An IT Elective 4 Project +paths: + /api/v1/accounts/jwt/create/: + post: + operationId: api_v1_accounts_jwt_create_create + description: |- + Takes a set of user credentials and returns an access and refresh JSON web + token pair to prove the authentication of those credentials. + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TokenObtainPair' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/TokenObtainPair' + multipart/form-data: + schema: + $ref: '#/components/schemas/TokenObtainPair' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/TokenObtainPair' + description: '' + /api/v1/accounts/jwt/refresh/: + post: + operationId: api_v1_accounts_jwt_refresh_create + description: |- + Takes a refresh type JSON web token and returns an access type JSON web + token if the refresh token is valid. + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TokenRefresh' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/TokenRefresh' + multipart/form-data: + schema: + $ref: '#/components/schemas/TokenRefresh' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/TokenRefresh' + description: '' + /api/v1/accounts/jwt/verify/: + post: + operationId: api_v1_accounts_jwt_verify_create + description: |- + Takes a token and indicates if it is valid. This view provides no + information about a token's fitness for a particular use. + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TokenVerify' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/TokenVerify' + multipart/form-data: + schema: + $ref: '#/components/schemas/TokenVerify' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/TokenVerify' + description: '' + /api/v1/accounts/users/: + get: + operationId: api_v1_accounts_users_list + tags: + - api + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CustomUser' + description: '' + post: + operationId: api_v1_accounts_users_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserRegistration' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UserRegistration' + multipart/form-data: + schema: + $ref: '#/components/schemas/UserRegistration' + required: true + security: + - jwtAuth: [] + - {} + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/UserRegistration' + description: '' + /api/v1/accounts/users/{id}/: + get: + operationId: api_v1_accounts_users_retrieve + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this user. + required: true + tags: + - api + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + put: + operationId: api_v1_accounts_users_update + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this user. + required: true + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/CustomUser' + multipart/form-data: + schema: + $ref: '#/components/schemas/CustomUser' + required: true + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + patch: + operationId: api_v1_accounts_users_partial_update + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this user. + required: true + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + delete: + operationId: api_v1_accounts_users_destroy + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this user. + required: true + tags: + - api + security: + - jwtAuth: [] + responses: + '204': + description: No response body + /api/v1/accounts/users/activation/: + post: + operationId: api_v1_accounts_users_activation_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Activation' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Activation' + multipart/form-data: + schema: + $ref: '#/components/schemas/Activation' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Activation' + description: '' + /api/v1/accounts/users/me/: + get: + operationId: api_v1_accounts_users_me_retrieve + tags: + - api + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + put: + operationId: api_v1_accounts_users_me_update + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/CustomUser' + multipart/form-data: + schema: + $ref: '#/components/schemas/CustomUser' + required: true + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + patch: + operationId: api_v1_accounts_users_me_partial_update + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedCustomUser' + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CustomUser' + description: '' + delete: + operationId: api_v1_accounts_users_me_destroy + tags: + - api + security: + - jwtAuth: [] + responses: + '204': + description: No response body + /api/v1/accounts/users/resend_activation/: + post: + operationId: api_v1_accounts_users_resend_activation_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/SendEmailReset' + multipart/form-data: + schema: + $ref: '#/components/schemas/SendEmailReset' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + description: '' + /api/v1/accounts/users/reset_password/: + post: + operationId: api_v1_accounts_users_reset_password_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/SendEmailReset' + multipart/form-data: + schema: + $ref: '#/components/schemas/SendEmailReset' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + description: '' + /api/v1/accounts/users/reset_password_confirm/: + post: + operationId: api_v1_accounts_users_reset_password_confirm_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + multipart/form-data: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + description: '' + /api/v1/accounts/users/reset_username/: + post: + operationId: api_v1_accounts_users_reset_username_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/SendEmailReset' + multipart/form-data: + schema: + $ref: '#/components/schemas/SendEmailReset' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SendEmailReset' + description: '' + /api/v1/accounts/users/reset_username_confirm/: + post: + operationId: api_v1_accounts_users_reset_username_confirm_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UsernameResetConfirm' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UsernameResetConfirm' + multipart/form-data: + schema: + $ref: '#/components/schemas/UsernameResetConfirm' + required: true + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/UsernameResetConfirm' + description: '' + /api/v1/accounts/users/set_password/: + post: + operationId: api_v1_accounts_users_set_password_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SetPassword' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/SetPassword' + multipart/form-data: + schema: + $ref: '#/components/schemas/SetPassword' + required: true + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SetPassword' + description: '' + /api/v1/accounts/users/set_username/: + post: + operationId: api_v1_accounts_users_set_username_create + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SetUsername' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/SetUsername' + multipart/form-data: + schema: + $ref: '#/components/schemas/SetUsername' + required: true + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SetUsername' + description: '' +components: + schemas: + Activation: + type: object + properties: + uid: + type: string + token: + type: string + required: + - token + - uid + CustomUser: + type: object + properties: + username: + type: string + readOnly: true + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + email: + type: string + format: email + title: Email address + maxLength: 254 + avatar: + type: string + format: uri + first_name: + type: string + maxLength: 100 + last_name: + type: string + maxLength: 100 + required: + - avatar + - first_name + - last_name + - username + PasswordResetConfirm: + type: object + properties: + uid: + type: string + token: + type: string + new_password: + type: string + required: + - new_password + - token + - uid + PatchedCustomUser: + type: object + properties: + username: + type: string + readOnly: true + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + email: + type: string + format: email + title: Email address + maxLength: 254 + avatar: + type: string + format: uri + first_name: + type: string + maxLength: 100 + last_name: + type: string + maxLength: 100 + SendEmailReset: + type: object + properties: + email: + type: string + format: email + required: + - email + SetPassword: + type: object + properties: + new_password: + type: string + current_password: + type: string + required: + - current_password + - new_password + SetUsername: + type: object + properties: + current_password: + type: string + new_username: + type: string + title: Username + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + required: + - current_password + - new_username + TokenObtainPair: + type: object + properties: + username: + type: string + writeOnly: true + password: + type: string + writeOnly: true + access: + type: string + readOnly: true + refresh: + type: string + readOnly: true + required: + - access + - password + - refresh + - username + TokenRefresh: + type: object + properties: + access: + type: string + readOnly: true + refresh: + type: string + writeOnly: true + required: + - access + - refresh + TokenVerify: + type: object + properties: + token: + type: string + writeOnly: true + required: + - token + UserRegistration: + type: object + properties: + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + email: + type: string + format: email + password: + type: string + writeOnly: true + avatar: + type: string + format: uri + nullable: true + first_name: + type: string + maxLength: 100 + last_name: + type: string + maxLength: 100 + required: + - email + - first_name + - last_name + - password + - username + UsernameResetConfirm: + type: object + properties: + new_username: + type: string + title: Username + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + required: + - new_username + securitySchemes: + jwtAuth: + type: http + scheme: bearer + bearerFormat: JWT From 760915276720336dcf7aaa32fed7698bb901ed61 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Sun, 12 Nov 2023 21:45:39 +0800 Subject: [PATCH 3/3] Added all required functionality for equipments and equipment handling --- Pipfile | 1 + Pipfile.lock | 10 +- equipment_tracker/api/urls.py | 3 +- equipment_tracker/config/settings.py | 4 +- equipment_tracker/db.sqlite3 | Bin 131072 -> 184320 bytes equipment_tracker/equipments/__init__.py | 0 equipment_tracker/equipments/admin.py | 5 + equipment_tracker/equipments/apps.py | 6 + .../equipments/migrations/0001_initial.py | 66 ++++++++ ...move_equipment_last_changed_by_and_more.py | 25 +++ .../migrations/0003_historicalequipment.py | 40 +++++ .../equipments/migrations/__init__.py | 0 equipment_tracker/equipments/models.py | 50 ++++++ equipment_tracker/equipments/serializers.py | 157 ++++++++++++++++++ equipment_tracker/equipments/tests.py | 3 + equipment_tracker/equipments/urls.py | 29 ++++ equipment_tracker/equipments/views.py | 89 ++++++++++ 17 files changed, 485 insertions(+), 3 deletions(-) create mode 100644 equipment_tracker/equipments/__init__.py create mode 100644 equipment_tracker/equipments/admin.py create mode 100644 equipment_tracker/equipments/apps.py create mode 100644 equipment_tracker/equipments/migrations/0001_initial.py create mode 100644 equipment_tracker/equipments/migrations/0002_remove_equipment_last_changed_by_and_more.py create mode 100644 equipment_tracker/equipments/migrations/0003_historicalequipment.py create mode 100644 equipment_tracker/equipments/migrations/__init__.py create mode 100644 equipment_tracker/equipments/models.py create mode 100644 equipment_tracker/equipments/serializers.py create mode 100644 equipment_tracker/equipments/tests.py create mode 100644 equipment_tracker/equipments/urls.py create mode 100644 equipment_tracker/equipments/views.py diff --git a/Pipfile b/Pipfile index 627e336..bf53dd8 100644 --- a/Pipfile +++ b/Pipfile @@ -14,6 +14,7 @@ drf-spectacular = {version = "*", extras = ["sidecar"]} django-extra-fields = "*" pillow = "*" psycopg2 = "*" +django-simple-history = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index f1f704a..8120404 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7ca25164f3d5c5501004130b514ab73101cc9d6937aa0af8356bf65a3cb354fe" + "sha256": "ebe508cba3dbd2fa271c39d69ab71cb95f5630e21875aea04ad9f6893ced1877" }, "pipfile-spec": 6, "requires": { @@ -254,6 +254,14 @@ "index": "pypi", "version": "==3.0.2" }, + "django-simple-history": { + "hashes": [ + "sha256:19bd1a87e1e2eba34dfd43eab1fcf2da5752221f343232f2372b2121c7e3b97d", + "sha256:992dcca3cddc0b67b470fc91f77292e2d2a6010d37c9eac3536e9d80e8754032" + ], + "index": "pypi", + "version": "==3.4.0" + }, "django-templated-mail": { "hashes": [ "sha256:8db807effebb42a532622e2d142dfd453dafcd0d7794c4c3332acb90656315f9", diff --git a/equipment_tracker/api/urls.py b/equipment_tracker/api/urls.py index 14fb12e..03edd51 100644 --- a/equipment_tracker/api/urls.py +++ b/equipment_tracker/api/urls.py @@ -1,5 +1,6 @@ from django.urls import path, include urlpatterns = [ - path('accounts/', include('accounts.urls')) + path('accounts/', include('accounts.urls')), + path('equipments/', include('equipments.urls')) ] diff --git a/equipment_tracker/config/settings.py b/equipment_tracker/config/settings.py index 86a6e26..cc422ea 100644 --- a/equipment_tracker/config/settings.py +++ b/equipment_tracker/config/settings.py @@ -64,11 +64,13 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'rest_framework', 'rest_framework_simplejwt', + 'simple_history', 'djoser', 'corsheaders', 'drf_spectacular', 'drf_spectacular_sidecar', - 'accounts' + 'accounts', + 'equipments', ] MIDDLEWARE = [ diff --git a/equipment_tracker/db.sqlite3 b/equipment_tracker/db.sqlite3 index 151391c1e3878bf8ec113c43d881832c7b9b3572..87da6db199c737d132b64699dfe3dde8dc390bf9 100644 GIT binary patch literal 184320 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 delta 1281 zcmb`FO>7%Q6vuaVV>`*(8JjdXV*Rn9Ax&j!&+hE5cU>a7`KULk6FW`XwDb_wm?)NL z?8vx|_>vtsAfeDkQ)#IqfBx+;-Lt@yPb^zcsDTg!E>81B+lg* zMM@5Z19a}^1>y^i0Kpj&Z}+mepUgZm^bj&cNy;c{2FXbSV-;(pAQ)~eD=JpWTY}`q z62&t4SrA=VHw+bH5{w)U9n7ukDw4=##GP8#bc9rLC4$^JGzrn@?<3faRg92K9*(Bn zSWytdWI3w2G1d@L$WHXQ8_Tq$PX3Cz-RLsvluXBDceJ#h/logs/', + views.EquipmentLogViewSet.as_view({'get': 'list'})), + # Last changed equipment + path('equipments/latest', views.LastUpdatedEquipmentViewSet.as_view()), + # Logs for all equipment instances + path('equipment_instances/logs', views.EquipmentInstancesLogsViewSet.as_view()), + # Logs for each equipment instance + path('equipment_instances//logs/', + views.EquipmentInstanceLogViewSet.as_view({'get': 'list'})), + # Last changed equipment instance + path('equipment_instances/latest', + views.LastUpdatedEquipmentInstanceViewSet.as_view()) +] diff --git a/equipment_tracker/equipments/views.py b/equipment_tracker/equipments/views.py new file mode 100644 index 0000000..b97306d --- /dev/null +++ b/equipment_tracker/equipments/views.py @@ -0,0 +1,89 @@ +from rest_framework.permissions import IsAuthenticated +from rest_framework import viewsets, generics +from .models import Equipment, EquipmentInstance +from . import serializers +from config.settings import DEBUG + +# -- Equipment Viewsets + + +class EquipmentViewSet(viewsets.ModelViewSet): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentSerializer + queryset = Equipment.objects.all().order_by('-date_added') + +# For viewing all logs for all equipments + + +class EquipmentsLogsViewSet(generics.ListAPIView): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentLogsSerializer + queryset = Equipment.history.all().order_by('-history_date') + +# For viewing logs per individual equipment + + +class EquipmentLogViewSet(viewsets.ReadOnlyModelViewSet): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentLogSerializer + + def get_queryset(self): + equipment_id = self.kwargs['equipment_id'] + return Equipment.objects.filter(id=equipment_id) + +# Last changed equipment + + +class LastUpdatedEquipmentViewSet(generics.ListAPIView): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentSerializer + queryset = Equipment.objects.all().order_by('-date_added') + + def get_queryset(self): + return super().get_queryset()[:1] + +# -- Equipment Instance Viewsets + + +class EquipmentInstanceViewSet(viewsets.ModelViewSet): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentInstanceSerializer + queryset = EquipmentInstance.objects.all().order_by('-date_added') + +# For viewing all equipment instance logs + + +class EquipmentInstancesLogsViewSet(generics.ListAPIView): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentInstanceLogsSerializer + queryset = EquipmentInstance.history.all().order_by('-history_date') + +# For viewing logs per individual equipment instance + + +class EquipmentInstanceLogViewSet(viewsets.ReadOnlyModelViewSet): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentInstanceLogSerializer + + def get_queryset(self): + equipment_id = self.kwargs['equipment_id'] + return EquipmentInstance.objects.filter(id=equipment_id) + +# Last changed equipment instance + + +class LastUpdatedEquipmentInstanceViewSet(generics.ListAPIView): + if (not DEBUG): + permission_classes = [IsAuthenticated] + serializer_class = serializers.EquipmentInstanceSerializer + queryset = EquipmentInstance.objects.all().order_by('-date_added') + + def get_queryset(self): + return super().get_queryset()[:1]